Jekyll2021-03-25T12:20:50-04:00https://paulhe.com/feed.xmlPaul HePaul HeTeaching as a PhD Student (WIP)2020-08-29T00:00:00-04:002020-08-29T00:00:00-04:00https://paulhe.com/2020/08/29/teaching-online<p>I did a good deal of teaching during the 2019-2020 school year.
This was an eventful time period.</p>
<p>Teaching is a part of most PhD programs, at least in the US and Canada.
At Penn, the requirement is to act as a teaching assistant (TA) for 2 semesters.
I did very little TAing in undergrad but I knew that teaching was something I wanted to do more of.
I decided to go further than TAing, and to instead teach my own class.</p>
<h2 id="fall-and-spring-c-programming">Fall and Spring: C++ Programming</h2>
<p>Penn offers <a href="https://www.cis.upenn.edu/~cis19x/">CIS 19x</a> classes, half-credit “minicourses” taught by students, with half the lecture time of a normal class.
This was the most straightforward way I knew of to teach a course at Penn, so I applied with a short teaching demo of C++ I/O streams and became the C++ minicourse instructor.
C++ was one of the first programming languages I learned, and by far the language I had the most experience with.
Out of the list of previous 19x classes, it was clear to me that this would be one of the few I was qualified to teach.</p>
<p>I was pretty excited about designing the course.
While I could use material from the last time this course was offered, that offering was way back in 2015.
That last iteration of the course spent many weeks on C, and continued on to then introduce C++ features.
This is the classic C++ course structure, and I wanted to do something different.
While I and many other programmers learned C++ in this way, this method often ends up creating “C with classes” programmers and fails to teach programmers how to write idiomatic C++.
Such a coding style often leads to complaints about the language, complaints that often just go away if one uses the proper abstractions in modern C++.</p>
<p>I decided I would redesign the course to instead teach <em>modern</em> C++, that is, C++17 <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup>.
Since Penn undergraduates learn C in one of their required classes, I decided to skip the C portion of previous offerings.
Instead of starting from C and adding on C++ features one by one, I would start with C++ as its own language and not as an “upgrade” to C.
I would introduce the idiomatic features of C++ as <em>the</em> solution and not an alternative style compared to C.
For example, rather than present standard library containers or smart pointers as an alternative to C data structures or pointers, I would present them as the first tool one should turn to in C++.</p>
<p>Like most of the other 19x classes, the grade would be largely based on homeworks and a final project, without any formal exams.
I had few requirements on the final project.
Students could work in small groups to make whatever they were interested in, as long as they used some of the features of C++ we covered in class.</p>
<h3 id="fall-2019">Fall 2019</h3>
<p>The fall semester would be my first semester of teaching.
As a first-time instructor, the class would be fairly small with only around 15 students.
I also had one undergraduate teaching assistant to help me with office hours and grading.</p>
<p>Unsurprisingly, I couldn’t find any comprehensive resources for teaching C++17 from scratch, so I decided to create my own.
For the topics, I drew heavily from the second edition of <a href="https://www.stroustrup.com/tour2.html">“A Tour of C++”</a> by Bjarne Stroustrup, one of only a few books at the time to cover C++17.
I had all summer to prepare for the class, but this of course didn’t go well.
I made a rough schedule of topics to cover, but I was mostly preparing my lectures as I went.
It took about two full days of work to put together each week’s 1.5 hour lecture and weekly assignment.
This was a lot more time than I expected.
I was not very familiar with some of the newer features of C++, so I had to first learn them and then come up with a way to present them nicely.</p>
<p>During class, I would write on the board and present code on the projector.
TODO more stuff about the actual class.
The class went well.
Student feedback was fairly positive and I think my students had fun.</p>
<h3 id="spring-2020">Spring 2020</h3>
<p>For the spring semester, I knew I wanted to make some changes to the class.</p>
<p>One issue I had in the fall was that It was easy for students to get lose when I was editing code, a common thing I do in my lectures to show different ways to solve a problem.
For example, if I switched from the first code snippet to the second, would you know what had happened? <sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">eg3</span> <span class="n">or</span> <span class="n">something</span>
</code></pre></div></div>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">eg4</span> <span class="n">or</span> <span class="n">something</span>
</code></pre></div></div>
<p>To help with this, I stopped showing code on the projector and instead, mostly wrote code on the board.
Erasing one part of the code and replacing it is a lot more noticible and easy to show emphasis.
This had the added benefit of slowing down my lectures.
In the fall I sped through my material more quickly than I expected and—despite C++ being such a large language—actually ran out of language features to teach.</p>
<p>Another issue I had in the fall was checking student understanding.
Often I would get questions about a topic that I had thought was clear from lecture, since there were no in-class questions about it.
Sometimes, these questions were quite fundamental to understanding the material, such as understanding memory allocation or pointers.
To combat this, I added polls to my lectures.
A few times a class I would put up a small question to check students’ understanding.
These polls were used for participation grades, but were not checked for correctness.
These were very useful in finding topics that I might have missed in class or questions students couldn’t articulate well in lecture.</p>
<h2 id="going-online">Going Online</h2>
<p>In March, COVID-19 was declared a pandemic.
Penn was on its spring break at the time, so many students were away from campus.
The spring break was extended by a week and I frantically started planning for lectures on Zoom.
Luckily, I already owned a Microsoft Surface with a pen, so I could continue lecturing in the same style I was in person.
I would write code using the pen and sometimes switch to my terminal to show the output of a program.</p>
<p>The last few months of the semester continued online.
My online lectures mostly went smoothly, though attendance was lower and there were occasional issues with my connection or forgetting to push the record button in Zoom.</p>
<h2 id="summer-automata-computability-and-complexity">Summer: Automata, Computability, and Complexity</h2>
<p>Earlier in 2020, I decided to teach the undergraduate theory of computation class in the summer.
Due to rising enrollments in computer science, this would help reduce strain on class sizes during the regular school year.
I made this decision before the pandemic started, so originally I was supposed to teach in person, but like many instructors I transitioned to online teaching.</p>
<h3 id="course-logistics">Course Logistics</h3>
<p>Penn’s summer classes are largely organized in two five-week sessions.
My class was scheduled for the second summer session, which was from the beginning of July to August.
This class is the same as the standard theory of computation class during the normal school year, so it would have the same amount of material and same number of lecture hours, about 8 hours per week spread out over 4 days.</p>
<p>Since this was a summer class, I decided to organize it as an asynchronous class using videos rather than live lectures.
I assumed that many students would have other obligations, like summer jobs.
I also thought it would be easier on international students in other time zones, and I also didn’t think I could lecture live for 2 hours straight, 4 days a week.
I ordered a slightly nicer microphone than my laptop mic, and prepared myself.
I planned to record several videos for each day’s lecture, one for each small topic or example.</p>
<p>Between me and my TAs, we held office hours every day of the week at different times (ranging from 9am to 11pm EDT), to try to be accessible to as many different time zones as possible.</p>
<h3 id="experience">Experience</h3>
<p>I had most of the summer to prepare for the class, but this of course didn’t go well.
I was mostly preparing my lectures as I went.</p>
<p>Preparing for this class took up a very significant amount of time.
Almost all my working hours were dedicated to the course.
Planning and recording lectures took up the most time.
I had to go over the textbook material and create notes for what I would cover in each video.
Then I had to record the video, and I would rewatch the recording (at a higher playback speed) to check for mistakes.
There were also homeworks and an exam to create and grade, and finally helping students in office hours and in Piazza.</p>
<p>I thought the course went fairly well.
For some reason, course evaluations were not required as they usually are, so I didn’t get as much feedback from students as I would normally.
One piece of feedback I received was that there should have been some sort of recitation or Q&A session.</p>
<p>Originally, I thought the daily office hours and Piazza would be enough.
Maybe they were, but at the end of the course I held some review sessions for the exam.
Though attendance wasn’t high, it was a nice experience for me as well—seeing the students and having them ask questions in real time was an experience I hadn’t even realized I missed.</p>
<p>If I were to do it again, I would perhaps prerecord the fundamental material, theorems, proofs, and such, and also hold live sessions where I do more in-depth examples and applications.
This would also have the added benefit of pushing the students to keep up with the daily videos.
The majority of students only watched the videos when a new homework came out.</p>
<h2 id="teaching-is-cool">Teaching is cool</h2>
<p>Would recommend</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>This was in 2019, before the release of C++20. I’ll be updating the course to C++20 next time I teach it. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>asdf <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>Paul HeI did a good deal of teaching during the 2019-2020 school year. This was an eventful time period.Weak weeks2019-10-23T00:00:00-04:002019-10-23T00:00:00-04:00https://paulhe.com/2019/10/23/weak-weeks<p>In August I tried to abandon the concept of the days of the week.</p>
<p>I had very few scheduled responsibilities: only a single meeting scheduled for each week.
The goal was to reduce mood changes due to the day of the week, like getting no work done on Fridays and disappointment on Sundays.
Though studies on this <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup> suggest that there is little support for some of these phenomena, I wanted to see for myself.</p>
<p>The first few week were fine; I’d try to go to work around five days a week, and take days off when I felt like I needed one.
I especially tried to work on weekends, since I was more productive (or at least happier with music on my speakers) when the office was empty.
This was a pretty good setup.
I felt like I had a lot of flexibility and got a decent amount done.</p>
<p>But then I got a cat.
I stayed home way too much to watch her, even though she was still adjusting and wasn’t especially playful.
The summer ended with me doing far less than I wanted to.
Nevertheless, I’d like to try this experiment again, especially since it seemed fruitful from the first few weeks.</p>
<p>Anyways, here’s some photos of my cat Strawberry, the real reason for the post.</p>
<p><img src="/assets/strawberry1.jpg" alt="Strawberry" />
<img src="/assets/strawberry2.jpg" alt="Strawberry" />
<img src="/assets/strawberry3.jpg" alt="Strawberry" />
<img src="/assets/strawberry4.jpg" alt="Strawberry" />
<img src="/assets/strawberry5.jpg" alt="Strawberry" />
<img src="/assets/strawberry6.jpg" alt="Strawberry" /></p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>Arthur A. Stone, Stefan Schneider & James K. Harter (2012) Day-of-week mood patterns in the United States: On the existence of ‘Blue Monday’, ‘Thank God it’s Friday’ and weekend effects, The Journal of Positive Psychology, 7:4, 306-314, DOI: 10.1080/17439760.2012.691980 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>Paul HeIn August I tried to abandon the concept of the days of the week.Coinduction2019-04-17T00:00:00-04:002019-04-17T00:00:00-04:00https://paulhe.com/2019/04/17/coinduction<p>Coinduction is the mathematical dual to an indispensible mathematical tool: induction.
While mathematical induction has been known for thousands of years, coinduction has only been studied for a few decades.
It is still primarily used in computer science, from which it originated in the field of concurrency theory.
Coinduction allows us to define circular or <em>infinite</em> objects (such as <a href="https://en.wikipedia.org/wiki/Stream_(computer_science)">streams</a>, lists that can be infinitely long), and to prove things about them.</p>
<p>It should not be confused with <a href="https://en.wikipedia.org/wiki/Coinduction_(anaesthetics)">this coinduction</a>, which may put you to sleep instead.</p>
<h2 id="inductive-definitions">Inductive definitions</h2>
<p>Inductive (or recursive) definitions are ubiquitous in mathematics, to the point where they are often implicit.
They follow a common pattern to build up a set of objects incrementally.
A base case (or multiple) is first established, and then rules for building up objects based on previous levels are defined.</p>
<p>The set of finite strings \(S\) on an alphabet \(\Sigma\) is the set inductively defined by the following rules, in <a href="https://en.wikipedia.org/wiki/Rule_of_inference">inference rule</a> notation:</p>
\[\frac{}{\epsilon \in S} \qquad \frac{s \in S \quad \sigma \in \Sigma}{\sigma s \in S}\]
<p>So \(\epsilon\) (the empty string) is a string, and for any symbol \(\sigma\) in the alphabet, we can prepend that onto another string to yield a string.
Only the objects generated from the rules are in \(S\).</p>
<p>Inductive definitions can be thought of as an iterative process: we start with the empty set and keep adding objects according to the definition, until in the limit, we reach a <a href="https://en.wikipedia.org/wiki/Fixed_point_(mathematics)">fixed point</a>, when applying the rules no longer adds anything new to the set.
We add \(\epsilon\), then the length 1 strings, then the length 2 strings, and so on, until we have the infinite set of strings over \(\Sigma\) of any length in \(\mathbb{N}\).</p>
<p>An inductive definition is thus the <em>smallest</em> set closed <em>forward</em> under its defining rules.
That is, \(S\) is the smallest set such that \(\epsilon \in S\) and that if \(s \in S\), then \(\sigma s \in S\) for any \(\sigma \in \Sigma\).
We apply the rules from premises to conclusion.</p>
<h2 id="coinductive-definitions">Coinductive definitions</h2>
<p>Since coinduction is the dual to induction, let’s try “flipping” the inductive definition.
A coinductive definition is the <em>largest</em> set closed <em>backward</em> under its defining rules.</p>
<p>What does this mean?
For an inductive definition, we can think of the set as starting from \(\varnothing\) and iteratively adding elements according to the rules.
For a coinductive definition, we can think of the set as starting from the set of all possible objects (even infinite ones), and iterative removing objects that contradict the rules.</p>
<p>If we use the same rules that inductive defined \(S\) above, the coinductively defined set \(S'\) is the largest set such that \(\epsilon \in S'\) and that if \(\sigma s \in S\), then \(s \in S\) (and \(\sigma \in \Sigma\)).
Here, the backward closure goes from the conclusion to the premises, the opposite of the forward closure.
The set of finite strings, \(S\), is included in \(S'\).
But we also have some new strings in \(S'\), the infinitely long strings.
Consider the string \(s = aaaaaa \dots\), where \(a \in \Sigma\).
We cannot construct it using the base case, but it doesn’t lead to a contradiction either, since if \(s = aaaaa \dots \in S\), taking off the first \(a\) results in the same infinite string \(s\), and \(s \in S\) as desired.</p>
<p>The proof tree for \(s\) is infinite, and looks like the following:</p>
\[\large \frac{a \in \Sigma \quad \frac{ a \in \Sigma \quad \frac{ \cdots }{ aaa \dots \in S' } }{ aaa \dots \in S' }}{ aaa \dots \in S' }\]
<p>While objects of inductive definitions require finite derivations, objects of coinductive definitions can have infinite derivations.</p>
<h2 id="proof-principles">Proof principles</h2>
<p>For the following, I will skip over some (many) details.</p>
<p>The function \(F\) can be thought of as the set of rules for a given (co)inductive definition.
\(F(X)\) is the set of conclusions obtained after applying the rules using \(X\) as the set of premises.</p>
<p>Recall that an inductive definition is the least fixed point of a set of rules, and that a coinductive definition is the greatest fixed point.
Now here is a specialization of the Knaster–Tarski fixpoint theorem:</p>
<p><strong>Theorem:</strong> <br />
The least fixed point of \(F = \mu F = \bigcap \{ X \mid F(X) \subseteq X \}\). <br />
The greatest fixed point of \(F = \nu F = \bigcup \{ X \mid X \subseteq F(X) \}\).</p>
<p>\(F(X) \subseteq X\) captures the meaning of the informal “closed forwards” definition from earlier.
Given a set \(T\) where the premises \(X \subseteq T\), we can apply <em>all</em> rules in the “forwards” direction, obtaining the set of conclusions \(F(X)\) which are also in \(T\): \(F(X) \subseteq X \subseteq T\).</p>
<p>Dually, \(X \subseteq F(X)\) captures the meaning of “closed backwards”.
Given a set \(T\) where the conclusions \(F(X) \subseteq T\) from some set of premises \(X\), we can apply <em>some</em> rule for each \(t \in F(X)\) in the “backwards” direction, obtaining the set of premises \(X\) which are also in \(T\): \(X \subseteq F(X) \subseteq T\).</p>
<p>Simple corollaries of the fixpoint theorem gives us proof principles for inductive and coinductive definitions:</p>
<p><strong>Lemma (Induction Principle):</strong> <br />
If \(F(X) \subseteq X\), then \(\mu F \subseteq X\). <br />
<strong>Lemma (Coinduction Principle):</strong> <br />
If \(X \subseteq F(X)\), then \(X \subseteq \nu F\).</p>
<h3 id="proof-by-induction">Proof by induction</h3>
<p>Using the induction principle, we can show that every element of a inductively defined set satisfies some condition, by showing that the condition is preserved for each rule of the definition.</p>
<p>We can derive the more familiar principle of mathematical induction using this.
Let \(F(X) = \{ 0 \} \cup \{ 1 + x \mid x \in X \}\).
This is the set of rules for the natural numbers.
It may be more familiar if I write it as the following:</p>
\[\frac{}{0 \in \mathbb{N}} \qquad \frac{n \in \mathbb{N}}{1 + n \in \mathbb{N}}\]
<p>Then to prove some fact about the natural numbers, we just need to show that it is preserved when applying these rules in the forwards direction.
For example, we will show that \(1 + 2 + \dots + n = \frac{n(n+1)}{2}\) is true for all natural numbers.
Let’s take \(X = \{ n \in \mathbb{N} \mid 1 + 2 + \dots + n = \frac{n(n+1)}{2} \}\).
Then we will prove that \(\mu F = \mathbb{N} \subseteq X\).
This is exactly the conclusion of the Induction Principle, so we need to show that \(F(X) \subseteq X\).</p>
<p>An element of \(F(X)\) can either be \(0\) (the base case), which we can easily verify is in \(X\), or \(1 + n\) (the inductive case) where \(n \in X\) (the inductive hypothesis).
This should look familiar.
Some fiddling will show that the second case is true as well, and we are done! \(\Box\)</p>
<h3 id="proof-by-coinduction">Proof by coinduction</h3>
<p>Dually, using the coinduction principle, we can show that an element is in the coinductively defined set.</p>
<p>Using just \(S'\), our only coinductively defined set so far, would not be very interesting, since it would involve only the membership proofs we saw earlier.
Let’s make another coinductive definition, this time a relation on elements of \(S'\): let \(F(X) = \{ (\epsilon, \epsilon) \} \cup \{ (\sigma_1 s_1, \sigma_2 s_2) \mid \sigma_1 \le \sigma_2 \land (s_1, s_2) \in X \}\), where \(\le\) is some ordering on the alphabet (the usual one on the English alphabet, for instance).
Can you tell what relation this defines?
Let’s write down the inference rules:</p>
\[\frac{}{\epsilon \leqslant \epsilon} \qquad \frac{\sigma_1 \le \sigma_2 \qquad s_1 \leqslant s_2}{\sigma_1 s_1 \leqslant \sigma_2 s_2}\]
<p>The notation should help: \(\nu F\) is the lexicographic ordering relation on our (possibly) infinite strings, displayed here as \(\leqslant\).</p>
<p>Now we can prove that some strings are related by this relation.
For an example, we will show \(aaaa \dots \leqslant baaaa \dots\).
Note that these are infinitely long strings.</p>
<p>Using the coinduction principle, we just need to show that \((aaaa \dots, baaaa \dots)\) is in some set of pairs of strings that is closed backwards under \(F\).
Let’s try the singleton set \(X = \{(aaaa \dots, baaaa \dots)\}\) first.
Then \(F(X) = \{ (\epsilon, \epsilon) \} \cup \{ (\sigma_1 aaaa \dots, \sigma_2 baaaa \dots) \mid \sigma_1 \le \sigma_2 \}\).
But then \(X \not \subseteq F(X)\), since the second string of every pair in \(F(X)\) has a \(b\) as the second symbol.</p>
<p>\(X\) is our “coinductive hypothesis”.
Like how during induction we sometimes have to strengthen the inductive hypothesis, here we have to strengthen the coinductive hypothesis by making it bigger.</p>
<p>Recall the “backwards closed” intuition.
We want to show that by applying <em>some</em> rule “backwards”, we obtain something still in \(X\).
If we start with \((aaaa \dots, baaaa \dots)\), we can only apply the second rule, stripping off the first symbol of each string.
\(a \le b\), so that premise is fine, and we just need to show that \((aaaa \dots, aaaa \dots) \in X\) now.
It looks like we need to grow \(X\) by adding this new pair to it, strengthening the coinductive hypothesis.</p>
<p>Now \(X = \{ (aaaa \dots, baaaa \dots), (aaaa \dots, aaaa \dots) \}\), and \(F(X) = \{ (\epsilon, \epsilon) \} \cup \\ \{ (\sigma_1 aaaa \dots, \sigma_2 baaaa \dots) \mid \sigma_1 \le \sigma_2 \} \cup \\ \{ (\sigma_1 aaaa \dots, \sigma_2 aaaa \dots) \mid \sigma_1 \le \sigma_2 \}\)</p>
<p>Let’s check that \(X \subseteq F(X)\). <br />
\((aaaa \dots, baaaa \dots) = (a\cdot aaaa \dots, b\cdot aaaa \dots)\), and \(a \le b\). <br />
\((aaaa \dots, aaaa \dots) = (a\cdot aaaa \dots, a\cdot aaaa \dots)\), and \(a \le a\).</p>
<p>And since \((aaaa \dots, baaaa \dots) \in X\), we’re done! \(\Box\)</p>
<h2 id="conclusion">Conclusion</h2>
<p>Recently I’ve been working on <a href="https://github.com/DeepSpec/InteractionTrees/">Interaction Trees</a>, a library that provides a coinductive data structure for reasoning about interactive programs in Coq.
Coinduction is less convenient than induction in Coq.
For example, in the coinductive proof above the “coinductive hypothesis” included exactly the conclusion we were trying to prove.
When doing the proof informally, we know we must apply one of the rules backwards and only then can we apply the coinductive hypothesis.</p>
<p>Doing this in a proof assistant like Coq is more complex.
Using “vanilla” Coq, it will allow you to apply the coinductive hypothesis immediately, and then complain that you got it wrong when you try to finish the proof.
The <a href="https://github.com/snu-sf/paco">paco</a> library solves this problem, but more complex reasoning quickly gets complex, which is why I started learning more about the theory behind coinduction.</p>
<p>I find it really intriguing how (relatively) new coinduction is and how useful it has become.
There’s been a lot of work recently on areas related to coinduction, and I’m excited to do more work in this area.</p>
<h2 id="resources">Resources</h2>
<p>I first encountered coinduction in <a href="https://www.cis.upenn.edu/~bcpierce/tapl/">Types and Programming Languages</a> by Benjamin C. Pierce, where they are introduced to talk about the metatheory of recursive types. While I wouldn’t recommend reading this if you’re <em>just</em> interested in coinduction, it serves as an excellent introduction to programming languages and type systems.</p>
<p><a href="http://www.cs.unibo.it/~sangio/IntroBook.html">Introduction to Bisimulation and Coinduction</a> by Davide Sangiorgi is a very accessible textbook that goes into detail about all of this and more.
It cleared up a lot of questions I had about coinduction, and helped me understand it more rigorously.</p>Paul HeCoinduction is the mathematical dual to an indispensible mathematical tool: induction. While mathematical induction has been known for thousands of years, coinduction has only been studied for a few decades. It is still primarily used in computer science, from which it originated in the field of concurrency theory. Coinduction allows us to define circular or infinite objects (such as streams, lists that can be infinitely long), and to prove things about them.Welcome2019-03-06T00:00:00-05:002019-03-06T00:00:00-05:00https://paulhe.com/2019/03/06/first-post<p>Welcome to my blog! This is the first (official) post, hopefully of many.</p>
<h2 id="goals">Goals</h2>
<p>I decided to start this blog because I rarely write anything longer than a sentence at a time, which seems like a useful thing to practice for a PhD student.
I’ve also always felt pretty weak at communicating about research or technical stuff (not to mention just in general).
Hopefully this will help me with these things, as well as improve my understanding of the technical material I’ll be writing about.</p>
<p>I plan to write about various technical things I encounter during my research work.
These will probably be things related to functional programming and programming language theory.</p>
<h2 id="website">Website</h2>
<p>Let me tell you a bit about the inner workings of the website, which I spent (and will continue to spend) a lot of time on—instead of writing posts.
The site is static, hosted on <a href="https://pages.github.com/">Github Pages</a>, and is generated by <a href="https://jekyllrb.com/">Jekyll</a>.
I don’t want to handle any complexity related to hosting, so a static website seems fine to me.</p>
<p>However if you look at the bottom of the page, you’ll see something less standard: an ugly hacked together comment system.
I originally tried using <a href="https://disqus.com/">Disqus</a>, which was really quite nice and easy to use.
You can see an example of it on my blog <a href="/2019/02/28/first-post.html">here</a>.</p>
<p>I preferred something more lightweight though, and also something I controlled entirely.
Here’s an <a href="/2019/02/28/second-post.html">example</a> of what my current solution looks like.
You can even embed html (what’s sanitization?)!</p>
<p>I’m using <a href="https://staticman.net/">Staticman</a> to display user-generated content.
When a comment is submitted, it goes through the Staticman web service, which creates a pull request on my website’s Github repo to add the comment as a text file, to be included in the (updated) static site.</p>
<p>I think this is super cool.
No databases or anything to deal with!
Staticman was pretty nice to use, though the documentation is a little out of date.
Originally it was run as a single public instance, and due to the number of users it had it was hitting the rate limit for the Github API (see <a href="https://github.com/eduardoboucas/staticman/issues/243">this Github issue</a> for details).
The developer then updated Staticman to be a Github app, so each user would get their own instance and thus their own API quota.
However, this was fairly recent (Dec 2018) and the documentation wasn’t updated to reflect this, so it took me a few hours to get it working.</p>
<p><strong>Edit</strong> Oct 3: Staticman died at some point! The service is open source, so maybe I will host my own instance on Heroku. <br />
<strong>Edit</strong> Aug 18 2020: Finally hosted my own instance on Heroku.</p>
<h2 id="to-come">To Come</h2>
<p>I’ll be working on updating the site a bit more to add a navigation menu (<strong>Edit</strong> Mar 7: Done!), less ugly comments (<strong>Edit</strong> Mar 8: Arguably done!), and so on.
For my research I’ll be spending most of my time in the next few weeks on coinduction, a very cool proof technique, and I hope to write something introductory about it soon.</p>Paul HeWelcome to my blog! This is the first (official) post, hopefully of many.Blogging Like a Hacker2019-02-28T00:00:00-05:002019-02-28T00:00:00-05:00https://paulhe.com/2019/02/28/first-post<h1 id="test">Test</h1>
<div id="disqus_thread"></div>
<script>
/**
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
* LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables
*/
/*
var disqus_config = function () {
this.page.url = https://paulhe.com/2019/02/28/first-post.html
this.page.identifier = /2019/02/28/first-post
};
*/
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://paulhe.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
<script id="dsq-count-scr" src="//paulhe.disqus.com/count.js" async=""></script>Paul HeTestComments2019-02-28T00:00:00-05:002019-02-28T00:00:00-05:00https://paulhe.com/2019/02/28/second-postPaul He