<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: 林子篆</title>
    <description>The latest articles on Forem by 林子篆 (@dannypsnl).</description>
    <link>https://forem.com/dannypsnl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F74313%2Ffbab7864-1fee-4c9c-b909-ae5b2a8425a5.png</url>
      <title>Forem: 林子篆</title>
      <link>https://forem.com/dannypsnl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dannypsnl"/>
    <language>en</language>
    <item>
      <title>A wrong question: Is a Square a Rectangle?</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Mon, 16 Nov 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/a-wrong-question-is-a-square-a-rectangle-2pk8</link>
      <guid>https://forem.com/dannypsnl/a-wrong-question-is-a-square-a-rectangle-2pk8</guid>
      <description>&lt;p&gt;Overview&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;what is Subtyping?&lt;/li&gt;
&lt;li&gt;what is Liskov Substitution Principle?&lt;/li&gt;
&lt;li&gt;what's the problem?&lt;/li&gt;
&lt;li&gt;how to solve this mistake of type system&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is Subtyping?
&lt;/h3&gt;

&lt;p&gt;A common misunderstanding is OOP must have &lt;strong&gt;subtyping&lt;/strong&gt; and &lt;strong&gt;generic&lt;/strong&gt; at the same time, but they are independent features, &lt;strong&gt;generic&lt;/strong&gt; is just a type-level function with takes a type, generates a type. &lt;strong&gt;Subtyping&lt;/strong&gt; is a relationship between type, when we say &lt;code&gt;A &amp;lt;: B&lt;/code&gt;, which means &lt;code&gt;A&lt;/code&gt; is a subtype of &lt;code&gt;B&lt;/code&gt;. In Java, we use concrete syntax &lt;code&gt;extends&lt;/code&gt; or &lt;code&gt;implements&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Liskov Substitution Principle(LSP)?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LSP&lt;/strong&gt; said&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering the program&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What's the problem
&lt;/h3&gt;

&lt;p&gt;Square is a special Rectangle where all four sides are equal in length. Thus we might write down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Rectangle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;initX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initX&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setX&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setY&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Square&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;initX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;SquareException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initX&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SquareException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initX&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initY&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so we can have following program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setX&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oops, &lt;code&gt;s&lt;/code&gt; is not a square anymore, this correctly follows &lt;strong&gt;LSP&lt;/strong&gt; but incorrect generally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Here is a solution: refinement type. By using refinement type, we can claim &lt;code&gt;type Square = Rectangle when (x = y)&lt;/code&gt;. Then problem solved, when programming if we can't proof &lt;code&gt;x = y&lt;/code&gt; this predicate then compiler won't think that is a &lt;code&gt;Square&lt;/code&gt; but a &lt;code&gt;Rectangle&lt;/code&gt;. Since &lt;code&gt;Square&lt;/code&gt; is a &lt;code&gt;Rectangle&lt;/code&gt;, method in &lt;code&gt;Rectangle&lt;/code&gt; still can be using by &lt;code&gt;Square&lt;/code&gt;, thus we didn't lose our power. However, program like &lt;code&gt;s.setX(v)&lt;/code&gt;, would need to prove &lt;code&gt;v = y&lt;/code&gt;, to prove it is a &lt;code&gt;Square&lt;/code&gt;. Here we have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;change &lt;code&gt;s&lt;/code&gt; type to &lt;code&gt;Rectangle&lt;/code&gt;, the problem of this solution is if we write &lt;code&gt;r = s; r.setX(v)&lt;/code&gt;, compiler might not work for this(this is also why I'm designing &lt;a href="https://github.com/dannypsnl/controllable-refinement"&gt;controllable-refinement&lt;/a&gt;), mutable semantic always needs more effort.&lt;/li&gt;
&lt;li&gt;throw compile error that &lt;code&gt;Square&lt;/code&gt; constraint was broke by the statement.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Choose one and work with it, that's all, have a nice day.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to find mk fixed point</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sun, 26 Jul 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/how-to-find-mk-fixed-point-if2</link>
      <guid>https://forem.com/dannypsnl/how-to-find-mk-fixed-point-if2</guid>
      <description>&lt;p&gt;This article is about how to get a fixed point in lambda calculus(utlc) system, if you didn't familiar with it, you can read &lt;a href="https://dev.to/blog/2020/01/01/cs/note-what-is-lambda-calculus/"&gt;NOTE: what is lambda calculus&lt;/a&gt; to get start. What's a fixed point? When a function f(x)f(x)f(x) has xxx can make f(x)=xf(x) = xf(x)=x then we say xxx is the fixed point of fff. Now we can get start to derive one.&lt;/p&gt;

&lt;p&gt;In lambda calculus, Peano's number can be represented as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;z: λs.λz.z\lambda s . \lambda z . zλs.λz.z&lt;/li&gt;
&lt;li&gt;s z: λs.λz.s  z\lambda s . \lambda z . s \; zλs.λz.sz&lt;/li&gt;
&lt;li&gt;s s z: λs.λz.s  (s  z)\lambda s . \lambda z . s \; (s \; z)λs.λz.s(sz)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then &lt;strong&gt;s&lt;/strong&gt; (successor) can be found.&lt;/p&gt;

&lt;p&gt;s≐λn.λs.λz.s  (n  s  z)s \doteq \lambda n . \lambda s . \lambda z . s \; (n \; s \; z)s≐λn.λs.λz.s(nsz)&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;s&lt;/strong&gt; , we can define &lt;strong&gt;add&lt;/strong&gt; , idea is simple: find number nnn successor of mmm.&lt;/p&gt;

&lt;p&gt;add≐λn.λm.m  (s  n)add \doteq \lambda n . \lambda m . m \; (s \; n)add≐λn.λm.m(sn)&lt;/p&gt;

&lt;p&gt;We can check a number is zero or not(assume true/false already defined) and predecessor.&lt;/p&gt;

&lt;p&gt;iszero≐λn.n  (λx.false)  truepredecessor≐λn.λs.λz.second  (n  (wrap  f)&amp;lt;true,x&amp;gt;)wrapf≐λp.&amp;lt;false,if  (first  p)  (second  p)  (f  (second  p))&amp;gt;iszero \doteq \lambda n . n \; (\lambda x . false) \; true \&lt;br&gt;
predecessor \doteq \lambda n . \lambda s . \lambda z . second \; (n \; (wrap \; f) &amp;lt;true, x&amp;gt;) \&lt;br&gt;
wrap f \doteq \lambda p . &amp;lt;false, if \; (first \; p) \; (second \; p) \; (f \; (second \; p))&amp;gt;iszero≐λn.n(λx.false)truepredecessor≐λn.λs.λz.second(n(wrapf))wrapf≐λp.&lt;/p&gt;

&lt;p&gt;p.s. &lt;a&gt; represents a pair, first is a, and second is b. Assuming &lt;code&gt;first&lt;/code&gt; and &lt;code&gt;second&lt;/code&gt; already bound.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these, we can define &lt;code&gt;mult&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;mult≐λn.λm.if  (iszero  n)  0  (add  m  (mult  (predecessor  n)  m))mult \doteq \lambda n . \lambda m . if \; (iszero \; n) \; 0 \; (add \; m \; (mult \; (predecessor \; n) \; m))mult≐λn.λm.if(iszeron)0(addm(mult(predecessorn)m))&lt;/p&gt;

&lt;p&gt;However, lambda didn't have a name(all ≐\doteq≐ was name tag for human only, not allowed in lambda calculus), so we cannot refer to &lt;code&gt;mult&lt;/code&gt; in &lt;code&gt;mult&lt;/code&gt;! But we can have a proper version.&lt;/p&gt;

&lt;p&gt;mkmult≐λn.λm.if  (iszero  n)  0  (add  m  ((t  t)  (predecessor  n)  m))mkmult \doteq \lambda n . \lambda m . if \; (iszero \; n) \; 0 \; (add \; m \; ((t \; t) \; (predecessor \; n) \; m))mkmult≐λn.λm.if(iszeron)0(addm((tt)(predecessorn)m))&lt;/p&gt;

&lt;p&gt;How to use this?&lt;/p&gt;

&lt;p&gt;mult≐(mkmult  mkmult)mult \doteq (mkmult \; mkmult)mult≐(mkmultmkmult)&lt;/p&gt;

&lt;p&gt;The key was a recursively expanded definition for &lt;code&gt;mult&lt;/code&gt;. &lt;code&gt;t t&lt;/code&gt; always take a &lt;code&gt;mkmult&lt;/code&gt; and make more &lt;code&gt;mkmult&lt;/code&gt;. Thus, can we generalize this?&lt;/p&gt;

&lt;p&gt;mk≐λt.t(mk  t)mk \doteq \lambda t . t (mk \; t)mk≐λt.t(mkt)&lt;/p&gt;

&lt;p&gt;Oops, but wait, we can repeat the pattern.&lt;/p&gt;

&lt;p&gt;mkmk≐λk.λt.t  ((k  k)  t)mkmk \doteq \lambda k . \lambda t . t \; ((k \; k) \; t)mkmk≐λk.λt.t((kk)t)&lt;/p&gt;

&lt;p&gt;Then we have &lt;code&gt;mk&lt;/code&gt;, for sure.&lt;/p&gt;

&lt;p&gt;mk≐(mkmk  mkmk)mk \doteq (mkmk \; mkmk)mk≐(mkmkmkmk)&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;mk&lt;/code&gt; we can have &lt;code&gt;mult&lt;/code&gt; by a different way.&lt;/p&gt;

&lt;p&gt;mkmult′≐λn.λm.if  (iszero  n)  0  (add  m  (t  (predecessor  n)  m))mult≐(mkmkmult′)mkmult' \doteq \lambda n . \lambda m . if \; (iszero \; n) \; 0 \; (add \; m \; (t \; (predecessor \; n) \; m))&lt;br&gt;
mult \doteq (mk mkmult')mkmult′≐λn.λm.if(iszeron)0(addm(t(predecessorn)m))mult≐(mkmkmult′)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mk&lt;/code&gt; can find out fixed point of any function. Which means &lt;code&gt;M (mk M) = (mk M)&lt;/code&gt;. &lt;code&gt;mk&lt;/code&gt; is not the only fixed point, the most famous fixed point is Y combinator, but I'm not going to talk about it here. At the end, thanks for the read and have a nice day.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hindley-Milner type system: Incrementally build way &amp; Make new language in Racket</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sun, 24 May 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/hindley-milner-type-system-incrementally-build-way-make-new-language-in-racket-307j</link>
      <guid>https://forem.com/dannypsnl/hindley-milner-type-system-incrementally-build-way-make-new-language-in-racket-307j</guid>
      <description>&lt;p&gt;Hindley-Milner (HM) type system is a classical type system for lambda calculus with parametric polymorphism. Its most notable property is it can infer most types of a given program, &lt;strong&gt;without type annotations&lt;/strong&gt;! However, this feature sounds cool but not work well in practice XD, since people need annotation to hint ourselves when reading. I pick this system as a topic is because the HM type system probably is the easiest completeness system with parametric polymorphism. It's a good start for understanding other more complex type systems, and it's important for gradual typing. But before we dig too deep into those ideas, let's start to understand HM, the point of this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why?
&lt;/h3&gt;

&lt;p&gt;In earlier days Lisp didn't have a type system, as time pass, people start to want to(or need to) express program more precisely since cooperation and robustness. Then people start working for their needs. To express a &lt;code&gt;list&lt;/code&gt;, introduce &lt;strong&gt;parametric polymorphism&lt;/strong&gt;. &lt;strong&gt;parametric polymorphism&lt;/strong&gt; sounds scared but doesn't, let's view an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;list-length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;All&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This syntax bind &lt;code&gt;list-length&lt;/code&gt; to a type &lt;code&gt;(All (A) (-&amp;gt; (List A) Integer))&lt;/code&gt;, or we would write &lt;code&gt;list-length : (All (A) (-&amp;gt; (List A) Integer))&lt;/code&gt;(you can see &lt;strong&gt;Racket&lt;/strong&gt; use prefix operator, very Lisp style, not surprise XD). The syntax is not the most important thing, but it shows a very common thing in many different languages, to help you get what is &lt;strong&gt;parametric polymorphism&lt;/strong&gt;. Now imagine, every time call &lt;code&gt;list-length&lt;/code&gt;, must provide &lt;code&gt;A&lt;/code&gt; as an argument: &lt;code&gt;(list-length Number lst)&lt;/code&gt;. People would get tired and say: I hate the static type system, it seems no surprise. That's the reason for type inference. With type inference, if &lt;code&gt;lst : (Listof Number)&lt;/code&gt;, &lt;code&gt;A&lt;/code&gt; is &lt;code&gt;Number&lt;/code&gt;, get type without type! The idea is so frustrating and makes people crazy to think about: Can we have a system, get all the type without type? The result is the HM type system.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Polymorphism
&lt;/h4&gt;

&lt;p&gt;In &lt;a href="https://dev.to/blog/cs/note-stlc/"&gt;simply typed lambda calculus (STLC)&lt;/a&gt;, asking &lt;strong&gt;e : T&lt;/strong&gt; make sense because we already give &lt;code&gt;e&lt;/code&gt; a type &lt;code&gt;K&lt;/code&gt;, check &lt;code&gt;T&lt;/code&gt; is &lt;code&gt;K&lt;/code&gt; is all we need. All type in STLC is a &lt;code&gt;T&lt;/code&gt; or &lt;code&gt;T -&amp;gt; T&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; will not from another type. This feature, however, makes inconvenience when writing a program, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Identity function can work well with any type, but now we have to provide infinite versions for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;id-str&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id-str&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;id-int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id-int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;id-bool&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id-bool&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;id-int-to-int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id-int-to-int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If I don't want it and still want types, then use polymorphism is the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;All&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I hope I convince you that, take your time to understand its detail of this system is valuable :).&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup a project
&lt;/h3&gt;

&lt;p&gt;This section helps you get a project would be modified in the following part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;raco pkg new hindley-milner
&lt;span class="nb"&gt;cd &lt;/span&gt;hindley-milner
raco pkg &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--auto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Syntax Overview
&lt;/h3&gt;

&lt;p&gt;I would show a small enough language can cooperate with HM type system and big enough to convince you this is useful, detail would not be the point, put them at here is just want to help you keep going with the following content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definition of language(create &lt;code&gt;lang.rkt&lt;/code&gt;):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;expr:int&lt;/span&gt; &lt;span class="nv"&gt;expr:bool&lt;/span&gt; &lt;span class="nv"&gt;expr:string&lt;/span&gt; &lt;span class="nv"&gt;expr:list&lt;/span&gt; &lt;span class="nv"&gt;expr:variable&lt;/span&gt; &lt;span class="nv"&gt;expr:lambda&lt;/span&gt; &lt;span class="nv"&gt;expr:application&lt;/span&gt; &lt;span class="nv"&gt;expr:let&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:int&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:bool&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:string&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:list&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;elems&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:variable&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:lambda&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;param&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:application&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;expr:let&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;bindings&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Pair&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Definition of types(create &lt;code&gt;typ.rkt&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;typ:builtin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;typ:builtin&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I will not explain them immediately, but let our incrementally steps show the story, let's start the journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part I: Incrementally build up inference
&lt;/h3&gt;

&lt;p&gt;Then we learn how to incrementally build up the HM type system without memorizing all rules. It also shows how to get ideas behind rules, not just remember a snapshot!&lt;/p&gt;

&lt;h4&gt;
  
  
  Monomorphism stuff
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Monomorphism&lt;/strong&gt;, which means obviously and decidable, and it would be a good start. Here, code can explain it better(create &lt;code&gt;semantic.rkt&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s"&gt;"lang.rkt"&lt;/span&gt;
         &lt;span class="s"&gt;"typ.rkt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:int&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:builtin&lt;/span&gt; &lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:bool&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:builtin&lt;/span&gt; &lt;span class="s"&gt;"bool"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:string&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:builtin&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see why I say they are obviously even you never use &lt;strong&gt;static type&lt;/strong&gt;, because this type is builtin in most language, inference their types is just by definition. &lt;code&gt;1&lt;/code&gt; is &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;#t&lt;/code&gt; is &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;"hello"&lt;/code&gt; is &lt;code&gt;string&lt;/code&gt;. However, there has a common &lt;strong&gt;builtin&lt;/strong&gt; type is not monomorphism, for example: &lt;code&gt;list&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  List
&lt;/h4&gt;

&lt;p&gt;The inference list type is not that easy, because it's a type depends on the type, what's that mean? It means we say: &lt;code&gt;list A&lt;/code&gt; is a type when &lt;code&gt;A&lt;/code&gt; is a type, so must have a type &lt;code&gt;A&lt;/code&gt; to have type &lt;code&gt;list A&lt;/code&gt;, this called type depends on the type. This means, if we want to inference type of list, we also need to inference the type of its element and check rest elements following the same type. An edge case is somehow, some lists do not contain any element, in such case we still need a type, so we give it a placeholder of the type usually called &lt;strong&gt;free type variable(freevar)&lt;/strong&gt;. Finally, returns a type &lt;code&gt;list&lt;/code&gt; with its type of argument. You can try to build it by yourself, but you would find there is something missing and became a wall stop you. The first thing we need to do, is extending our type definition to fit &lt;strong&gt;a type with type parameter&lt;/strong&gt; this abstraction(modify &lt;code&gt;typ.rkt&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Listof&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;typ:builtin&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;typ:constructor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:builtin&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;typ:builtin&lt;/code&gt; is just a special case of &lt;code&gt;typ:constructor&lt;/code&gt;, and we introduce the placeholder: &lt;code&gt;typ:freevar&lt;/code&gt;. The second thing need to prepare is &lt;strong&gt;Context&lt;/strong&gt;(modify &lt;code&gt;semantic.rkt&lt;/code&gt;, put them before &lt;code&gt;type/infer&lt;/code&gt;), which maintaining the state of &lt;code&gt;freevar&lt;/code&gt; counting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;Context&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;freevar-counter&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;
  &lt;span class="nt"&gt;#:mutable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Context/new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Context/new-freevar!&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Context&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new-freevar!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;cur-count&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context-freevar-counter&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set-Context-freevar-counter!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context-freevar-counter&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;cur-count&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then we can start adding inference of &lt;code&gt;expr:list&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;unify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;al&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;bl&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
     &lt;span class="nt"&gt;#:when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string=?&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;for-each&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;ae&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;be&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;ae&lt;/span&gt; &lt;span class="nv"&gt;be&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
               &lt;span class="nv"&gt;al&lt;/span&gt; &lt;span class="nv"&gt;bl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"cannot unify type ~a and ~a"&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;

&lt;span class="c1"&gt;; -&amp;gt;* is a special type, which means `-&amp;gt;* list-of-required-parameters list-of-optional-parameters return-type`&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:string&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:builtin&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:list&lt;/span&gt; &lt;span class="nv"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="s"&gt;"list"&lt;/span&gt;
                      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="nv"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new-freevar!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;; use first element type as type of all elements&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;elem-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt; &lt;span class="c1"&gt;; (car (list 1 2 3)) is 1&lt;/span&gt;
                          &lt;span class="c1"&gt;; check all elements follow first element type&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;for-each&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;elem&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;elem-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
                            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr&lt;/span&gt; &lt;span class="nv"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;; (cdr (list 1 2 3)) is (list 2 3)&lt;/span&gt;
                          &lt;span class="nv"&gt;elem-typ&lt;/span&gt;&lt;span class="p"&gt;)))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Currently, &lt;code&gt;unify&lt;/code&gt; just check two constructors has the same name, and keep &lt;code&gt;unify&lt;/code&gt; their parameters if has. In other cases, throw an exception.&lt;/p&gt;

&lt;h4&gt;
  
  
  Variable
&lt;/h4&gt;

&lt;p&gt;A variable would have a type, or it binds with a type. Anyway, that means we can infer the type of variable, but we need a place to store this information. Therefore, a new abstraction introduced &lt;strong&gt;Environment&lt;/strong&gt;(modify &lt;code&gt;semantic.rkt&lt;/code&gt;, put code before &lt;code&gt;Context&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;parent&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Option&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-env&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Mutable-HashTable&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;
  &lt;span class="nt"&gt;#:mutable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env/new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;Option&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/new&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;parent&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env&lt;/span&gt; &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make-hash&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
&lt;span class="c1"&gt;;;; Env/lookup take variable name such as `x` to get a type from env&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env/lookup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/lookup&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;lookup-parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;lookup-parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Option&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env-parent&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;parent&lt;/span&gt;
                              &lt;span class="c1"&gt;; dispatch to parent if we have one&lt;/span&gt;
                              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/lookup&lt;/span&gt; &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                              &lt;span class="c1"&gt;; really fail if we have no parent environment&lt;/span&gt;
                              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"no variable named: `~a`"&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
  &lt;span class="c1"&gt;; try to get value from table&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;typ-env&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Mutable-HashTable&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env-type-env&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-ref&lt;/span&gt; &lt;span class="nv"&gt;typ-env&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;
              &lt;span class="c1"&gt;; if fail, handler would take&lt;/span&gt;
              &lt;span class="nv"&gt;lookup-parent&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;then add a new field into &lt;code&gt;Context&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;Context&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;freevar-counter&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-env&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="nt"&gt;#:transparent&lt;/span&gt;
  &lt;span class="nt"&gt;#:mutable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Context/new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/new&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can get the variable type from &lt;code&gt;Context&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:variable&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/lookup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context-type-env&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait, we use variable then must somewhere we define it, where is it? Therefore, the next section is lambda, lambda would introduce new variables into the environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lambda
&lt;/h4&gt;

&lt;p&gt;Things are getting more complex, get really to understand what we need to do? Lambda in the HM system well not have type annotation for parameters, it causes the same problem just like what &lt;code&gt;list&lt;/code&gt; gives us. This means we need to bind a &lt;code&gt;freevar&lt;/code&gt; with parameters as variables into a &lt;strong&gt;new environment&lt;/strong&gt;. At here, since the multiple parameters are valid in this language, I introduce type &lt;code&gt;pair&lt;/code&gt; to abstraction on this rather than extend type definition. Then, we use this new environment to infer the type of body, and produce arrow type(If you don't understand arrow type, I suggest you read &lt;a href="https://dev.to/blog/cs/note-stlc/"&gt;STLC&lt;/a&gt; for explanation) via the inferred result. Now, it's time for some program:&lt;/p&gt;

&lt;h5&gt;
  
  
  Bind variable
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env/bind-var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/bind-var&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env-type-env&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;hash-has-key?&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"redefined: `~a`"&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-set!&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="nv"&gt;var-name&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Infer
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:lambda&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="c1"&gt;; params use new freevars as their type&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;letrec&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;λ-env&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context-type-env&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
           &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;param-types&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt;
                         &lt;span class="s"&gt;"pair"&lt;/span&gt;
                         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;param-name&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;r&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new-freevar!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
                                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/bind-var&lt;/span&gt; &lt;span class="nv"&gt;λ-env&lt;/span&gt; &lt;span class="nv"&gt;param-name&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                  &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set-Context-type-env!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt; &lt;span class="nv"&gt;λ-env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;body-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="nv"&gt;param-types&lt;/span&gt; &lt;span class="nv"&gt;body-typ&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;WARN: notice since I always invoke &lt;code&gt;type/infer&lt;/code&gt; without context in outside, &lt;code&gt;type-env&lt;/code&gt; no need to set back to the original one. However, if you extend this language with &lt;code&gt;define&lt;/code&gt; such sharing &lt;code&gt;Context&lt;/code&gt;, then set environment back is required, else your local bindings would affect the outer scope.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lambda seems powerful, and let can be translated to lambda, right? Unfortunately, it's correct in the computation view, but incorrect in the inference view. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It gets an identity function and applies to &lt;code&gt;1&lt;/code&gt;, it seems like it should get &lt;code&gt;int&lt;/code&gt;. However, we would get a &lt;code&gt;freevar&lt;/code&gt;. Because no one requires &lt;code&gt;id&lt;/code&gt; start infer its type since we have no idea when would lambda apply to something, if remove &lt;code&gt;(λ (a) a)&lt;/code&gt; and application form outside of &lt;code&gt;(λ (id) (id 1))&lt;/code&gt;, we cannot ensure the type of &lt;code&gt;(id 1)&lt;/code&gt;. That's what let polymorphism going to solve.&lt;/p&gt;

&lt;h4&gt;
  
  
  Let polymorphism
&lt;/h4&gt;

&lt;p&gt;Let polymorphism is the key expression in the HM type system, which ensures inference is decidable. The problem in the previous section can be fixed if using &lt;code&gt;let&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;let&lt;/code&gt; would infer the type of &lt;code&gt;id&lt;/code&gt; immediately. Then the problem would be eliminated. So the only different part between &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;lambda&lt;/code&gt;, is &lt;code&gt;let&lt;/code&gt; bind its variable with inferred type, not &lt;code&gt;freevar&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:let&lt;/span&gt; &lt;span class="nv"&gt;bindings&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;letrec&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;let-env&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Env&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context-type-env&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
              &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;bind-to-context&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Pairof&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
                                 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;bind&lt;/span&gt;
                                   &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;init&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Env/bind-var&lt;/span&gt; &lt;span class="nv"&gt;let-env&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;init&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)))))])&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;bind-to-context&lt;/span&gt; &lt;span class="nv"&gt;bindings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set-Context-type-env!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt; &lt;span class="nv"&gt;let-env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we came to infer the last expression: &lt;code&gt;expr:application&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Application
&lt;/h4&gt;

&lt;p&gt;Infer &lt;code&gt;application&lt;/code&gt; needs to do a few checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For application &lt;code&gt;(func args ...)&lt;/code&gt;, infer the type of &lt;code&gt;func&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check type of &lt;code&gt;func&lt;/code&gt; is a arrow type: &lt;code&gt;A -&amp;gt; B&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Assume return type is a &lt;code&gt;freevar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Unify &lt;code&gt;A -&amp;gt; B&lt;/code&gt; with &lt;code&gt;(typeof (args ...)) -&amp;gt; freevar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;return &lt;code&gt;freevar&lt;/code&gt; as infer result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With the explanation, we can start coding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;expr:application&lt;/span&gt; &lt;span class="nv"&gt;fn&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;fn-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;fn&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
           &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;args-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;arg&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
           &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;fresh&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Context/new-freevar!&lt;/span&gt; &lt;span class="nv"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;fn-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="s"&gt;"pair"&lt;/span&gt; &lt;span class="nv"&gt;args-typ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;fresh&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
       &lt;span class="nv"&gt;fresh&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="c1"&gt;; don't forget to close parenthesis!&lt;/span&gt;
  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We almost complete, but we have new jobs in &lt;code&gt;unify&lt;/code&gt; to do since application might unify &lt;code&gt;freevar&lt;/code&gt; and arrow type now.&lt;/p&gt;

&lt;h5&gt;
  
  
  Unify freevar
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;unify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="nv"&gt;p1&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="nv"&gt;p2&lt;/span&gt; &lt;span class="nv"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;p1&lt;/span&gt; &lt;span class="nv"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt; &lt;span class="nv"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;;;; freevar type is only important thing in `unify` function&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eqv?&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;occurs&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subst!&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;unify&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; ignore&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unify arrow type is simple, in fact, we can totally replace &lt;code&gt;typ:arrow&lt;/code&gt; with &lt;code&gt;typ:constructor&lt;/code&gt; XD. In fact, all type constructors can be &lt;code&gt;unify&lt;/code&gt; in the same way. &lt;code&gt;freevar&lt;/code&gt; brings a new thing: &lt;code&gt;occurs&lt;/code&gt;, what's &lt;code&gt;occurs&lt;/code&gt;?&lt;/p&gt;

&lt;h5&gt;
  
  
  Occurs check
&lt;/h5&gt;

&lt;p&gt;Occurs check make unification fail when unify &lt;code&gt;V&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt;, &lt;code&gt;T&lt;/code&gt; contains &lt;code&gt;V&lt;/code&gt;. If we didn't do this check, &lt;code&gt;unify&lt;/code&gt; would lead to unsound inference, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;?0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;?0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What would &lt;code&gt;?0&lt;/code&gt; be? It would cause an infinite loop at there: &lt;code&gt;(list (list (list ...)))&lt;/code&gt;. Therefore, we need to check if &lt;code&gt;V&lt;/code&gt; occurs in &lt;code&gt;T&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;occurs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;occurs&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;; same freevar means `v` occurs in `t`, then should be rejected&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eqv?&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; arrow and constructor both just keep check on type parameters&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;occurs&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;occurs&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;type-params&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;foldl&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;pre-bool&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="nv"&gt;pre-bool&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;occurs&lt;/span&gt; &lt;span class="nv"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="no"&gt;#f&lt;/span&gt;
            &lt;span class="nv"&gt;type-params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;; rest is fine&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, the whole inference part done, if you want to know how to build a new language in Racket then keep going, or you can close the tab now XD.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part Two: Make new language in Racket
&lt;/h3&gt;

&lt;p&gt;After we build up a type system, we definitely want to see it work as a language, and make a new language in Racket is crazy easy! Let's start the second part.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pretty Print
&lt;/h4&gt;

&lt;p&gt;First, to improve readability, we need pretty-print function(create &lt;code&gt;pretty-print.rkt&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s"&gt;"typ.rkt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="nv"&gt;pretty-print-typ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;typ:freevar&lt;/span&gt; &lt;span class="nv"&gt;idx&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"?~a"&lt;/span&gt; &lt;span class="nv"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;typ:constructor&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;typ-args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="nv"&gt;typ-args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"~a"&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;j&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-join&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;
                                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;typ-arg&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                                  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;typ-arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                                &lt;span class="nv"&gt;typ-args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string=?&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="s"&gt;"pair"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"(~a)"&lt;/span&gt; &lt;span class="nv"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"(~a ~a)"&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;typ:arrow&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"~a -&amp;gt; ~a"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and we modify the &lt;code&gt;unify&lt;/code&gt; function in &lt;code&gt;semantic.rkt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"cannot unify type ~a and ~a"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For example: &lt;code&gt;(typ:arrow (typ:constructor "int" '()) (typ:constructor "int" '()))&lt;/code&gt; would be &lt;code&gt;int -&amp;gt; int&lt;/code&gt;, very good.&lt;/p&gt;

&lt;h4&gt;
  
  
  Macro for module language
&lt;/h4&gt;

&lt;p&gt;Then we start handling macros in Racket, to handle the whole module, we need to overwrite &lt;code&gt;#%module-begin&lt;/code&gt;(modify &lt;code&gt;main.rkt&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;for-syntax&lt;/span&gt; &lt;span class="nv"&gt;syntax/parse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nv"&gt;racket/syntax&lt;/span&gt;
         &lt;span class="nv"&gt;syntax/stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s"&gt;"lang.rkt"&lt;/span&gt;
         &lt;span class="s"&gt;"semantic.rkt"&lt;/span&gt;
         &lt;span class="s"&gt;"pretty-print.rkt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;except-out&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;all-from-out&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%module-begin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rename-out&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;module-begin&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%module-begin&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax-rule&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;module-begin&lt;/span&gt; &lt;span class="nv"&gt;EXPR&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#%module-begin&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;all-form&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;EXPR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;for-each&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;displayln&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s"&gt;"type:- ~a~n"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
             &lt;span class="nv"&gt;all-form&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We haven't defined &lt;code&gt;parse&lt;/code&gt;, here shows how to get all forms in the module and handling them by &lt;code&gt;for-each&lt;/code&gt;, then is &lt;code&gt;parse&lt;/code&gt; part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;bind&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bind-name:id&lt;/span&gt; &lt;span class="nv"&gt;bind-expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="nt"&gt;#:with&lt;/span&gt; &lt;span class="nv"&gt;bind&lt;/span&gt;
             &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'bind-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;bind-expr&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;let&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binding*:bind&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;binding*&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;bind&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;λ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ps*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'ps*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;elem*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;elem*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;arg*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:application&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;arg*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;`v:id&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:variable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;`s:string&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#%datum&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;`b:boolean&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:bool&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#%datum&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;`i:exact-integer&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#%datum&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;span class="c1"&gt;;;; module-begin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Just mapping &lt;strong&gt;S expression&lt;/strong&gt; to expression defined in &lt;code&gt;lang.rkt&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Module reader
&lt;/h5&gt;

&lt;p&gt;Define a &lt;code&gt;module reader&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nv"&gt;reader&lt;/span&gt; &lt;span class="nv"&gt;syntax/module-reader&lt;/span&gt;
  &lt;span class="nv"&gt;hindley-milner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With these, you can use &lt;code&gt;#lang hindley-milner&lt;/code&gt; as new Racket program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;hindley-milner&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run it can see program prints expressions' structure and type.&lt;/p&gt;

&lt;h5&gt;
  
  
  REPL
&lt;/h5&gt;

&lt;p&gt;The final thing to do, that's REPL supporting, we need to overwrite &lt;code&gt;#%top-interaction&lt;/code&gt; to make it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;provide&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;except-out&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;all-from-out&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%module-begin&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%top-interaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rename-out&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;module-begin&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%module-begin&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;top-interaction&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;%top-interaction&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax-rule&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;top-interaction&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print-typ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type/infer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It gives a type after pretty print for input in REPL. Finally, we complete this journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope detailed implementation and examples show why we need the HM system, and how to make one, and where we would need it. I would be glad to hear you get help from this article. Have a nice day, and it's time for cookies!&lt;/p&gt;

&lt;p&gt;p.s. This is probably the second-longest article I made XD.&lt;/p&gt;

</description>
      <category>plt</category>
      <category>hindleymilner</category>
      <category>racket</category>
    </item>
    <item>
      <title>De Bruijn index: why and how</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sat, 16 May 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/de-bruijn-index-why-and-how-32f6</link>
      <guid>https://forem.com/dannypsnl/de-bruijn-index-why-and-how-32f6</guid>
      <description>&lt;p&gt;At the beginning of learning PLT, everyone would likely be confused by some program that didn't have a variable! Will, I mean they didn't use &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt; or something like that to define a variable. A direct mapping definition of lambda calculus(we would use &lt;strong&gt;LC&lt;/strong&gt; as the short name in the following context, and if you unfamiliar with &lt;strong&gt;LC&lt;/strong&gt; , you can read &lt;a href="https://dev.to/blog/cs/note-what-is-lambda-calculus/"&gt;this article&lt;/a&gt; first) usually looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;term:var&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;term:lambda&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;m&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;term:application&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;t2&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what we may find some definitions look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;typed/racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;bterm:var&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;v&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;bterm:lambda&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;m&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;bterm:application&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;t2&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nt"&gt;#:transparent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There has two significant different:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;variable is an &lt;code&gt;Integer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;lambda does not contain &lt;code&gt;x&lt;/code&gt;(which means parameter in high-level languages' concept).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is De Bruijn index(we would use &lt;strong&gt;DBI&lt;/strong&gt; as short name in the following context), we can write it out, for example, &lt;strong&gt;id&lt;/strong&gt; function &lt;code&gt;λx.x&lt;/code&gt; can be rewritten with &lt;code&gt;λ0&lt;/code&gt;, Y combinator &lt;code&gt;λf.(λx.f (x x)) (λx.f (x x))&lt;/code&gt; can be rewritten with &lt;code&gt;λ(λ0 (1 1))(λ0 (1 1))&lt;/code&gt;, but why? To understand &lt;strong&gt;DBI&lt;/strong&gt; , we need to know what was the problem in &lt;strong&gt;LC&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  α\alphaα-conversion
&lt;/h3&gt;

&lt;p&gt;Usually, two &lt;strong&gt;id&lt;/strong&gt; functions considered the same function. However, if we encode &lt;strong&gt;LC&lt;/strong&gt; as the first definition written in &lt;strong&gt;racket&lt;/strong&gt; , we would get into trouble: We may say &lt;code&gt;λx.x&lt;/code&gt; is not the same function as &lt;code&gt;λy.y&lt;/code&gt;, when they are the same. To solve this problem, we developed a conversion called &lt;strong&gt;α\alphaα-conversion&lt;/strong&gt; (or &lt;strong&gt;α\alphaα-renaming&lt;/strong&gt; ), which renaming &lt;code&gt;λx.x&lt;/code&gt; and &lt;code&gt;λy.y&lt;/code&gt; to &lt;code&gt;λa.a&lt;/code&gt;(&lt;code&gt;a&lt;/code&gt; is an abstraction variable, we can use any, any character to replace it) let's say. Looks good, any problem else? Emm...yes, as we know, the real world never make thing easier, but that also means a challenge is coming, and we all love the challenge! When a &lt;code&gt;λy.λx.x&lt;/code&gt; be renamed to &lt;code&gt;λa.λa.a&lt;/code&gt; is fine, because of every programmer work with variable-shadowing for a long-long time. However, there has a possible dangerous conversion is the renamed variable existed! For example, &lt;code&gt;λx.λa.x&lt;/code&gt; should not simply be rewritten with &lt;code&gt;λa.λa.a&lt;/code&gt;, because later when we rename &lt;code&gt;a&lt;/code&gt;, we would get &lt;code&gt;λa.λb.b&lt;/code&gt;, oops. &lt;code&gt;λx.λa.x&lt;/code&gt; definitely is not &lt;code&gt;λa.λb.b&lt;/code&gt;. To correct &lt;strong&gt;α\alphaα-conversion&lt;/strong&gt; is really hard, that's the main reason we introducing the De Bruijn index.&lt;/p&gt;

&lt;h3&gt;
  
  
  De Bruijn Index
&lt;/h3&gt;

&lt;p&gt;We already seem some examples, but why it resolves the problem we mentioned in the previous section? We need to know those rules used by the conversion process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;remember the level of &lt;code&gt;λ&lt;/code&gt;, every time we found a &lt;code&gt;λ&lt;/code&gt; when converting recursively, it should increase(or decrease, it depends on index order) this level value.&lt;/li&gt;
&lt;li&gt;when found a &lt;code&gt;λ&lt;/code&gt;, replace it's &lt;code&gt;x&lt;/code&gt; by variable using the De Bruijn index form, the value of the index is the current level.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's manually do this conversion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;λx.λy.λz.z
-&amp;gt; λλy.λz.z // x = cur_level = 0, cur_level+1
-&amp;gt; λλλz.z // y = cur_level = 1, cur_level+1
-&amp;gt; λλλ2 // z = cur_level = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that since new form of abstraction(a.k.a lambda) only needs &lt;code&gt;M&lt;/code&gt; part(a.k.a. body). Another important thing is some De Bruijn index use reverse order than we show at here, so would be &lt;code&gt;λλλ0&lt;/code&gt;, not &lt;code&gt;λλλ2&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation
&lt;/h4&gt;

&lt;p&gt;Now, it's time for the program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;convert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;term&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;Immutable-HashTable&lt;/span&gt; &lt;span class="nv"&gt;String&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;rename-to&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make-immutable-hash&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;())])&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;
    &lt;span class="c1"&gt;;; get index from environment&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;term:var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bterm:var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-ref&lt;/span&gt; &lt;span class="nv"&gt;rename-to&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;term:lambda&lt;/span&gt; &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bterm:lambda&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
               &lt;span class="c1"&gt;;; bind parameter name to an index&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-set&lt;/span&gt; &lt;span class="nv"&gt;rename-to&lt;/span&gt; &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-count&lt;/span&gt; &lt;span class="nv"&gt;rename-to&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;term:application&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bterm:application&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;rename-to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt; &lt;span class="nv"&gt;rename-to&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-&amp;gt;*&lt;/code&gt; is a type constructor in &lt;strong&gt;Racket&lt;/strong&gt; for &lt;strong&gt;optional&lt;/strong&gt; parameters, should be read like &lt;code&gt;(-&amp;gt;* normal-parameter-types optional-parameter-types return-type)&lt;/code&gt;. I use optional parameters to help users don't need to remember they must provide an empty hash table. A tricky thing is I didn't record level, at least, not directly. Here I use an immutable hash table to remember level, since how many variables should be renamed exactly is level value. Then variable only need to replace its name with the index.&lt;/p&gt;

&lt;p&gt;Congratulation, now you know everything about &lt;strong&gt;DBI&lt;/strong&gt;!? No, not yet, there still one thing you need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  β\betaβ-reduction
&lt;/h3&gt;

&lt;p&gt;β\betaβ-reduction? You might think how can such basic things make things go wrong. However, a naive implementation of β\betaβ-reduction can break structural equivalence of &lt;strong&gt;DBI&lt;/strong&gt; form, which can make an annoying bug in those systems based on &lt;strong&gt;LC&lt;/strong&gt;. The problem is lack-lifting. For example, a normal implementation of β\betaβ-reduction would simply make &lt;code&gt;λ(λλ2 0)&lt;/code&gt; become &lt;code&gt;λλ2&lt;/code&gt;. However, the same form directly converted from &lt;code&gt;λx.λz.z&lt;/code&gt; would become &lt;code&gt;λλ1&lt;/code&gt;, and &lt;code&gt;λλ2&lt;/code&gt; will be considered as different value as &lt;code&gt;λλ1&lt;/code&gt; since &lt;code&gt;1&lt;/code&gt; is not &lt;code&gt;2&lt;/code&gt;. We can introduce another renaming for these, but if we can fix it in β\betaβ-reduction, why need another phase?&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;beta-reduction&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;*&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Immutable-HashTable&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="nv"&gt;bterm&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;beta-reduction&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;de-bruijn-level&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;subst&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make-immutable-hash&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;())])&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;bterm:var&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-ref&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;bterm:lambda&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bterm:lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;beta-reduction&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;bterm:application&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt;
       &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;bterm:lambda&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;reduced-term&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;beta-reduction&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-set&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt;
          &lt;span class="c1"&gt;;;; dbi lifting by replace reduced-term (+ 1 dbi) with (var dbi)&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;beta-reduction&lt;/span&gt; &lt;span class="nv"&gt;reduced-term&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash-set&lt;/span&gt; &lt;span class="nv"&gt;subst&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bterm:var&lt;/span&gt; &lt;span class="nv"&gt;de-bruijn-level&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;raise&lt;/span&gt; &lt;span class="s"&gt;"cannot do application on non-lambda term"&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to record level independently since it has no relation with the substitution map this time. For variables, all need to do is apply substitution map to get value, if not, use origin form as a result. For the lambda, increase level is the only thing. For application, it's complicated. We need to be more careful with it. It contains three major parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;check &lt;code&gt;t1&lt;/code&gt; is an abstraction(a.k.a lambda), line 9 and 16&lt;/li&gt;
&lt;li&gt;do β\betaβ-reduction by add stuff into substitution map, line 11 to 12&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DBI&lt;/strong&gt; lifting (for example, &lt;code&gt;λλ2&lt;/code&gt; should become &lt;code&gt;λλ1&lt;/code&gt;), line 14 to 15&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DBI&lt;/strong&gt; is a quite useful technology when implementing complicated AST conversion. It's not just easier to avoid rename conflicting, but also a less memory required form for implementations. I hope you enjoy the article and have a nice day if this even really helps you in a real task, would be awesome!&lt;/p&gt;

</description>
      <category>plt</category>
      <category>racket</category>
    </item>
    <item>
      <title>How to parse expression with the parser combinator</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sun, 03 May 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/how-to-parse-expression-with-the-parser-combinator-582</link>
      <guid>https://forem.com/dannypsnl/how-to-parse-expression-with-the-parser-combinator-582</guid>
      <description>&lt;p&gt;WARN: As usual, I don't want to fix LaTeX stuff in the article.&lt;/p&gt;

&lt;p&gt;Writing parser is a boring and massive job, therefore, people create many ways like parser generators to reduce costs. One of them called parser combinator, parser combinator solves two problems: 1. didn't massive as the hand-crafted parser, 2. didn't impossible to debug like parser generator. Well, it sounds perfect, doesn't it? A parser combinator is great, but one thing could be a problem: precedence descent parser. Unlike parser generator usually provided builtin supporting for operators' precedence. Parser combinator usually only provided basic support for sequence and selective parsing. You probably already heard about &lt;a href="https://en.wikipedia.org/wiki/Operator-precedence_parser"&gt;operator precedence parser&lt;/a&gt;, let's first take a look at its pseudo code(provided by Wiki):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parse_expression()
    return parse_expression_1(parse_primary(), 0)
parse_expression_1(lhs, min_precedence)
    lookahead := peek next token
    while lookahead is a binary operator whose precedence is &amp;gt;= min_precedence
        op := lookahead
        advance to next token
        rhs := parse_primary ()
        lookahead := peek next token
        while lookahead is a binary operator whose precedence is greater
                 than op's, or a right-associative operator
                 whose precedence is equal to op's
            rhs := parse_expression_1 (rhs, lookahead's precedence)
            lookahead := peek next token
        lhs := the result of applying op with operands lhs and rhs
    return lhs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, this is not suitable to port on to a parser based on combinator, because figure out how to introduce state monad into parser monad is a complex job, but that would not be a problem since we have a more intuitive solution which starts from avoiding the left recursion. If you have ever taken a compiler class and it, unfortunately, spend most of the time on parsing, then you may be heard &lt;a href="https://en.wikipedia.org/wiki/Left_recursion"&gt;left recursion&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;A→AαA \rightarrow A \alphaA→Aα&lt;/p&gt;

&lt;p&gt;Where α\alphaα is any sequence of terminal and non-terminal symbols. For example:&lt;/p&gt;

&lt;p&gt;Expression→Expression+TermExpression \rightarrow Expression + TermExpression→Expression+Term&lt;/p&gt;

&lt;p&gt;A naive implementation would loop on &lt;code&gt;expression()&lt;/code&gt; forever. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;; in Racket, a char `k` express as `#\k`&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="sc"&gt;#\+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;term&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To solve this problem, first, we break down syntax:&lt;/p&gt;

&lt;p&gt;Factor→IntegerMultipleExpr→Factor  ∗  FactorAdditionExpr→MultipleExpr  +  MultipleExprFactor \rightarrow Integer \&lt;br&gt;
MultipleExpr \rightarrow Factor \; * \; Factor \&lt;br&gt;
AdditionExpr \rightarrow MultipleExpr \; + \; MultipleExprFactor→IntegerMultipleExpr→Factor∗FactorAdditionExpr→MultipleExpr+MultipleExpr&lt;/p&gt;

&lt;p&gt;Then we map them to parser combinators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="nv"&gt;data/monad&lt;/span&gt; &lt;span class="nv"&gt;data/applicative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="nv"&gt;megaparsack&lt;/span&gt; &lt;span class="nv"&gt;megaparsack/text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;lexeme/p&lt;/span&gt;
  &lt;span class="c1"&gt;;;; lexeme would take at least one space or do nothing&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;or/p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;many+/p&lt;/span&gt; &lt;span class="nv"&gt;space/p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;void/p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ss"&gt;'lexeme&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op/p&lt;/span&gt; &lt;span class="nv"&gt;op-list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;or/p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;one-of/p&lt;/span&gt; &lt;span class="nv"&gt;op-list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;void/p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;factor/p&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;integer/p&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lexeme/p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pure&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binary/p&lt;/span&gt; &lt;span class="nv"&gt;high-level/p&lt;/span&gt; &lt;span class="nv"&gt;op-list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;e&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;high-level/p&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;; `es` parse operator then high-level unit, for example, `* 1`.&lt;/span&gt;
    &lt;span class="c1"&gt;; therefore, this parser would stop when the operator is not expected(aka. operator is in op-list)&lt;/span&gt;
    &lt;span class="c1"&gt;; rely on this fact we can leave this loop&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;es&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;many/p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;op&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op/p&lt;/span&gt; &lt;span class="nv"&gt;op-list&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
                     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lexeme/p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;e&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;high-level/p&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;op&lt;/span&gt; &lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))))]&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;foldl&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;λ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op+rhs&lt;/span&gt; &lt;span class="nv"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;op+rhs&lt;/span&gt;
               &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;op&lt;/span&gt; &lt;span class="nv"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;op&lt;/span&gt; &lt;span class="nv"&gt;lhs&lt;/span&gt; &lt;span class="nv"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;
           &lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="nv"&gt;es&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;mul:div/p&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binary/p&lt;/span&gt; &lt;span class="nv"&gt;factor/p&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#\*&lt;/span&gt; &lt;span class="sc"&gt;#\/&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;add:sub/p&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binary/p&lt;/span&gt; &lt;span class="nv"&gt;mul:div/p&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#\+&lt;/span&gt; &lt;span class="sc"&gt;#\-&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;expr/p&lt;/span&gt; &lt;span class="nv"&gt;add:sub/p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check its result: &lt;code&gt;(parse-string expr/p "1 + 2 * 3 / 4 - 5")&lt;/code&gt; generate: &lt;code&gt;(success '(#\- (#\+ 1 (#\/ (#\* 2 3) 4)) 5))&lt;/code&gt; just as expected. Seems like &lt;code&gt;expr/p&lt;/code&gt; is our target, but it still is a little massive, doesn't it? We have to modify the definition of each small parser once we need to insert more infix operators. To avoid this, finally going to the purpose of this article, we need an automatic way to do this for us. Observing the definition of parsers, there has a pattern: every infix operator layer can be a &lt;code&gt;(binary/p high-level/p op-list)&lt;/code&gt;. Using this fact we can create a recursive function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;table/p&lt;/span&gt; &lt;span class="nv"&gt;base/p&lt;/span&gt; &lt;span class="nv"&gt;list-of-op-list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="nv"&gt;list-of-op-list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;base/p&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;table/p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;binary/p&lt;/span&gt; &lt;span class="nv"&gt;base/p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;list-of-op-list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr&lt;/span&gt; &lt;span class="nv"&gt;list-of-op-list&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;expr/p&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;table/p&lt;/span&gt; &lt;span class="nv"&gt;factor/p&lt;/span&gt;
           &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;#\*&lt;/span&gt; &lt;span class="sc"&gt;#\/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#\+&lt;/span&gt; &lt;span class="sc"&gt;#\-&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function takes a high-level parser and rest list of operator list. Use the head(&lt;code&gt;car&lt;/code&gt; in Racket) of the list of operator list to create a layer parser via &lt;code&gt;binary/p&lt;/code&gt;. If the list of operator list hasn't been empty, create more layers via &lt;code&gt;table/p&lt;/code&gt;. Now we can handle infinite infix operators! Now, is time to take a break and have fun, have a nice day!&lt;/p&gt;

</description>
      <category>parser</category>
      <category>racket</category>
    </item>
    <item>
      <title>Explain Homotopy type theory like I'm five</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Tue, 14 Apr 2020 06:06:16 +0000</pubDate>
      <link>https://forem.com/dannypsnl/explain-homotopy-type-theory-like-i-m-five-2pi0</link>
      <guid>https://forem.com/dannypsnl/explain-homotopy-type-theory-like-i-m-five-2pi0</guid>
      <description>&lt;p&gt;As the title, I'm looking for a clear overview summary of HOTT.&lt;/p&gt;

</description>
      <category>explainlikeimfive</category>
    </item>
    <item>
      <title>From Functor to Applicative</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sat, 11 Apr 2020 13:54:18 +0000</pubDate>
      <link>https://forem.com/dannypsnl/from-functor-to-applicative-377k</link>
      <guid>https://forem.com/dannypsnl/from-functor-to-applicative-377k</guid>
      <description>&lt;p&gt;Last time we introduce &lt;a href="https://dev.to/blog/cs/from-infinite-type-to-functor/"&gt;Functor&lt;/a&gt;, a &lt;a href="https://dev.to/blog/cs/from-infinite-type-to-functor/"&gt;Functor&lt;/a&gt; is a container which provide a function can help another function operating the &lt;a href="https://dev.to/blog/cs/from-infinite-type-to-functor/"&gt;Functor&lt;/a&gt;. This function has a name &lt;code&gt;fmap&lt;/code&gt; in &lt;strong&gt;Haskell&lt;/strong&gt;. Therefore, a function take a type &lt;code&gt;a&lt;/code&gt; as parameter(&lt;code&gt;a -&amp;gt; b&lt;/code&gt;) can be lifted by &lt;code&gt;fmap&lt;/code&gt; to handle &lt;code&gt;M a&lt;/code&gt;, if &lt;code&gt;M&lt;/code&gt; provided a &lt;code&gt;fmap&lt;/code&gt;. For example, &lt;code&gt;Maybe&lt;/code&gt; is a &lt;code&gt;Functor&lt;/code&gt;, &lt;code&gt;(+1)&lt;/code&gt; has the type &lt;code&gt;Int -&amp;gt; Int&lt;/code&gt;, &lt;code&gt;fmap (+1) (Just 10)&lt;/code&gt; get a result: &lt;code&gt;Just 11&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitation of Functor
&lt;/h3&gt;

&lt;p&gt;Oh, &lt;a href="https://dev.to/blog/cs/from-infinite-type-to-functor/"&gt;Functor&lt;/a&gt; seems so powerful, but programming is simple, life is hard! In the real world, a common situation is there has many &lt;code&gt;M&lt;/code&gt; have to handle. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;replicateMaybe&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;replicateMaybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;replicate&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;replicateMaybe&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;span class="n"&gt;replicateMaybe&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can see that we fall back to pattern matching, line 3 and 4 exclude no input. We can make it easier by extract out this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;liftMaybe2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="n"&gt;liftMaybe2&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;liftMaybe2&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;liftMaybe2 repliacte a b&lt;/code&gt; can work just as expected. Sounds great? How about lift &lt;code&gt;a -&amp;gt; b -&amp;gt; c -&amp;gt; d&lt;/code&gt; to &lt;code&gt;M a -&amp;gt; M b -&amp;gt; M c -&amp;gt; M d&lt;/code&gt;. How about make a lift to another &lt;code&gt;M&lt;/code&gt;, e.g. &lt;code&gt;List&lt;/code&gt;? &lt;code&gt;liftList&lt;/code&gt;? It seems like boilerplate code, right?&lt;/p&gt;

&lt;p&gt;Now we have two problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;liftMaybe_n&lt;/code&gt; problem, how to handle &lt;code&gt;liftMaybe&lt;/code&gt; for all &lt;code&gt;n&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;liftM&lt;/code&gt; problem, how to handle &lt;code&gt;lift&lt;/code&gt; for different &lt;code&gt;M&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Indeed, let's dig into &lt;code&gt;fmap&lt;/code&gt; again. Every function with type &lt;code&gt;a -&amp;gt; b&lt;/code&gt; become &lt;code&gt;M a -&amp;gt; M b&lt;/code&gt;, therefore, &lt;code&gt;a -&amp;gt; b -&amp;gt; c&lt;/code&gt; would be &lt;code&gt;M a -&amp;gt; M (b -&amp;gt; c)&lt;/code&gt;. The key point is how to make &lt;code&gt;M (b -&amp;gt; c)&lt;/code&gt; applied &lt;code&gt;b&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;applyMaybe&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;applyMaybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;applyMaybe&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now take a look at how magic happened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;applyMaybe&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;applyMaybe&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="c1"&gt;-- Just 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We solve &lt;code&gt;liftMaybe_n&lt;/code&gt; problem! The only problem is it only works for &lt;code&gt;Maybe&lt;/code&gt;, to solve the problem, it's the time of &lt;strong&gt;class&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applicative can help!
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Applicative&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt; is the general version of &lt;code&gt;applyMaybe&lt;/code&gt;. &lt;code&gt;pure&lt;/code&gt; could raise a variable into the calculation in &lt;code&gt;Applicative&lt;/code&gt;, we also call this &lt;strong&gt;minimum context&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Special helper &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt; has definition as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fmap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It just an alias of &lt;code&gt;fmap&lt;/code&gt; to help infix syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;-- Just 3&lt;/span&gt;
&lt;span class="n"&gt;replicate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="sc"&gt;'x'&lt;/span&gt;
&lt;span class="c1"&gt;-- Just "xxx"&lt;/span&gt;
&lt;span class="n"&gt;replicate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sc"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'z'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;-- ["x", "y", "z", "xx", "yy", "zz", "xxx", "yyy", "zzz"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope this article really help you understand why we need &lt;strong&gt;Applicative&lt;/strong&gt;. Next time would &lt;strong&gt;Monad&lt;/strong&gt; or &lt;strong&gt;monoid&lt;/strong&gt;, thanks for your read and have a good day!&lt;/p&gt;

</description>
      <category>plt</category>
      <category>applicative</category>
      <category>language</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Binary Encoding of Integer</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sat, 21 Mar 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/binary-encoding-of-integer-2n6e</link>
      <guid>https://forem.com/dannypsnl/binary-encoding-of-integer-2n6e</guid>
      <description>&lt;p&gt;Warning: I don't want to fix those LaTeX formulae anymore, go to &lt;a href="https://dannypsnl.github.io/docs/cs/binary-encoding-of-interger/"&gt;https://dannypsnl.github.io/docs/cs/binary-encoding-of-interger/&lt;/a&gt; if you want to see them.&lt;/p&gt;

&lt;p&gt;\mathbb{Z} contains positive and negative numbers, but nowdays Computer system based on binary. There only have &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; can be used. A simple solution is: &lt;strong&gt;put signed symbol at the most significant bit&lt;/strong&gt;. For example, use 8 bits can represent:&lt;/p&gt;

&lt;p&gt;-(2^7 - 1) = -127, -126, -125, … -0, +0, …, +125, +126, +(2^7 - 1) = +127&lt;/p&gt;

&lt;p&gt;This is an intuitive way. Therefore, early days computers applied it.&lt;/p&gt;

&lt;p&gt;But this way(called &lt;strong&gt;Sign magnitude&lt;/strong&gt; ) has two big problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;waste a place: +0 and -0 are different in this system&lt;/li&gt;
&lt;li&gt;have to detect signed or not and use different ways to do an operation like addition&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  One’s complement
&lt;/h3&gt;

&lt;p&gt;To solve the second problem with the calculation complex, engineers introduce &lt;strong&gt;one’s complement&lt;/strong&gt;. For example, a number: -43_{10} is 100101011_2, the one’s complement of it is 111010100_2(keep the most significant bit and reverse the rest of bits). It still only works for -127_{10} ... 127_{10} with 8 bits, didn’t solve the first problem obviously, why we say it solves the second one? Because we can replace special digital electronics with two subtractions:&lt;/p&gt;

&lt;p&gt;0010 - 0001 \equiv 0010 + (0011 - 0001) + (0001 - 0100)&lt;/p&gt;

&lt;p&gt;Then we convert negative number to one’s complement, and remember end-around carry(the bit over most significant bit should be add back), then get:&lt;/p&gt;

&lt;p&gt;0010 + 0011 + 1110 + 0001 + 1011&lt;br&gt;
\&lt;br&gt;
\to 0101 + 1110 + 0001 + 1011&lt;br&gt;
\&lt;br&gt;
\to 10011 + 0001 + 1011&lt;br&gt;
\&lt;br&gt;
\to 10100 + 1011&lt;br&gt;
\&lt;br&gt;
\to 1[1111]&lt;br&gt;
\&lt;br&gt;
\to 1111 + 0001&lt;br&gt;
\&lt;br&gt;
\to 1[0000]&lt;br&gt;
\&lt;br&gt;
\to 0000 + 0001&lt;br&gt;
\&lt;br&gt;
\equiv 0001&lt;/p&gt;

&lt;p&gt;Or 1110 + 0010 would get 1[0000] \to 0001&lt;/p&gt;

&lt;h5&gt;
  
  
  Benefit
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;no need to check signed bit&lt;/li&gt;
&lt;li&gt;reverse bits can use addition on subtraction&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Problem
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;need a special unit for end-around carry&lt;/li&gt;
&lt;li&gt;there still have two zero representations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Two’s complement
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Modular Arithmetic
&lt;/h5&gt;

&lt;p&gt;If we have an integer use 3 bits to represent, then 7 + 1 \equiv 0(mod \; 8) because of the overflow.&lt;/p&gt;

&lt;p&gt;If we have k bits for an integer, then we can generalize to A + B \equiv C(mod \; 2^k).&lt;/p&gt;

&lt;h5&gt;
  
  
  Abelian group
&lt;/h5&gt;

&lt;p&gt;For additive, we have to implement an Abelian group: an &lt;strong&gt;Identity&lt;/strong&gt; element and every element has an &lt;strong&gt;Inverse&lt;/strong&gt; element that adds them would get the &lt;strong&gt;Identity&lt;/strong&gt; element.&lt;/p&gt;

&lt;p&gt;Now consider how can our 3-bits integer fit rules of Abelian group? If &lt;code&gt;[000]&lt;/code&gt; represents &lt;code&gt;0&lt;/code&gt;, it’s identity in our group. Assuming &lt;code&gt;[001]&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;, how to know the representation of &lt;code&gt;-1&lt;/code&gt;? It’s easy to get &lt;code&gt;[111]&lt;/code&gt; this answer because we know &lt;code&gt;[111] + [001] = 1[000]&lt;/code&gt;, overflow would be dropped. And it cannot be any number except &lt;code&gt;-1&lt;/code&gt;, else we cannot find others inverse element of &lt;code&gt;1&lt;/code&gt;. With this, we can keep finding an inverse for &lt;code&gt;2&lt;/code&gt;(&lt;code&gt;[010]&lt;/code&gt;) is &lt;code&gt;[110]&lt;/code&gt; and so on.&lt;/p&gt;

&lt;p&gt;On the other hand, it still simple: &lt;code&gt;-1&lt;/code&gt; is the biggest negative number in 3-bits encoding. Follows unsigned order, &lt;code&gt;[111] &amp;gt; [110]&lt;/code&gt;, then don’t need another way to compare numbers.&lt;/p&gt;

&lt;h5&gt;
  
  
  Properties
&lt;/h5&gt;

&lt;p&gt;Now we can see we map all possible combinations of bits to an exact number. Solve the first problem in previous solutions.&lt;/p&gt;

&lt;p&gt;Even more, the subtractive of signed integer is additive of unsigned number: &lt;code&gt;010 + 101&lt;/code&gt; can be &lt;code&gt;2 + 5&lt;/code&gt; or &lt;code&gt;2 + (-3)&lt;/code&gt;. Therefore:&lt;/p&gt;

&lt;p&gt;A + \neg A = 2^k - 1&lt;br&gt;
\&lt;br&gt;
\to A + (\neg A + 1) = 2^k(mod \; 2^k)&lt;br&gt;
\&lt;br&gt;
\to -A := \neg A + 1&lt;/p&gt;

&lt;p&gt;Now we know we don’t need subtractive, it can be replaced with one’s complement plus one.&lt;/p&gt;

&lt;p&gt;Back to group, one’s complement would waste place about encoding is a thing must happen, because in 3-bits encoding it maps &lt;code&gt;[111]&lt;/code&gt; and &lt;code&gt;[000]&lt;/code&gt;. In two’s complement the axis of symmetry pass through &lt;code&gt;[000]&lt;/code&gt;, therefore, we won’t get repetitive representations of zero.&lt;/p&gt;

&lt;p&gt;Extend this &lt;code&gt;[001]&lt;/code&gt; maps to &lt;code&gt;[111]&lt;/code&gt; in two’s complement, maps to &lt;code&gt;[110]&lt;/code&gt; in one’s complement. Therefore, one’s complement plus one would be two’s complement.&lt;/p&gt;

</description>
      <category>fundamental</category>
    </item>
    <item>
      <title>NOTE: simply typed lambda calculus</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sun, 08 Mar 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/note-simply-typed-lambda-calculus-4142</link>
      <guid>https://forem.com/dannypsnl/note-simply-typed-lambda-calculus-4142</guid>
      <description>&lt;p&gt;Last time I introduce &lt;a href="https://dannypsnl.github.io/docs/cs/note-what-is-lambda-calculus/"&gt;lambda calculus&lt;/a&gt;.Lambda calculus is powerful enough for computation. But it’s not good enough for people, compare with below &lt;strong&gt;Church Numerals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;add:=λm.λn.λs.λz.m  s  (n  s  z)
add := \lambda m. \lambda n. \lambda s. \lambda z. m\;s\;(n\;s\;z)
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;dd&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λm&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λn&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mord mathnormal"&gt;z&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;z&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;people prefer just &lt;code&gt;+&lt;/code&gt; more.&lt;/p&gt;

&lt;p&gt;But once we introduce such fundamental operations into the system, validation would be a thing. This is the main reason to have a λ→ system(a.k.a. simply typed lambda calculus). It gets name λ→ is because it introduces one new type: Arrow type, represent as T1→T2 for any abstraction λx.M where x has a type is T1 and M has a type is T2. Therefore we can limit the input to a specified type, without considering how to add two &lt;code&gt;Car&lt;/code&gt; together!&lt;/p&gt;

&lt;p&gt;To represent this, syntax needs a little change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;term ::= terms
  x variable
  λx: T.term abstraction
  term term application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Abstraction now can describe it’s parameter type. Then we have typing rules:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;x:T∈ΓΓ⊢x:T        T−Variable
\frac{
  x:T \in \Gamma
  }{
  \Gamma \vdash x:T
  } \;\;\;\; T-Variable
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊢&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;∈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Va&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;iab&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Γ,x:T1⊢t2:T2Γ⊢λx:T1.t2:T1→T2        T−Abstraction
\frac{
  \Gamma, x:T_1 \vdash t_2: T_2
  }{
  \Gamma \vdash \lambda x:T_1.t_2 : T_1 \to T_2
  } \;\;\;\; T-Abstraction
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊢&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊢&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Γ,t1:T1→T2  Γ⊢t2:T1Γ⊢t1  t2:T2        T−Application
\frac{
  \Gamma, t_1:T_1 \to T_2 \; \Gamma \vdash t_2: T_1
  }{
  \Gamma \vdash t_1 \; t_2 : T_2
  } \;\;\;\; T-Application
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊢&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Γ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊢&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ppl&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;Here is the explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;T-Variable: with the premise, term x binds to type T in context Γ is truth. We can make a conclusion, in context Γ, we can judge the type of x is T.&lt;/li&gt;
&lt;li&gt;T-Abstraction: with the premise, with context Γ and term x binds to type T1 we can judge term t2 has type T2. We can make a conclusion, in context Γ, we can judge the type of λx:T1.t2 is T1→T2.&lt;/li&gt;
&lt;li&gt;T-Application: with the premise, with context Γ and term t1 binds to type T1→T2 and with context Γ we can judge term t2 has type T1. We can make a conclusion, in context Γ, we can judge the type of t1t2 is T2.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plt</category>
    </item>
    <item>
      <title>A Racket macro tutorial – get HTTP parameters easier</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Sun, 16 Feb 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/a-racket-macro-tutorial-get-http-parameters-easier-4jc9</link>
      <guid>https://forem.com/dannypsnl/a-racket-macro-tutorial-get-http-parameters-easier-4jc9</guid>
      <description>&lt;p&gt;A few days ago, I post this &lt;a href="https://dev.to/dannypsnl/comment/ldl8"&gt;answer&lt;/a&gt; to respond to a question about Racket's web framework. When researching on which frameworks could be used. I found no frameworks make get values from HTTP request easier. So I start to design a macro, which based on &lt;a href="//github.com/Junker/routy"&gt;routy&lt;/a&gt; and an assuming function &lt;code&gt;http-form/get&lt;/code&gt;, as following shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain this stuff. &lt;code&gt;get&lt;/code&gt; is a macro name, it's going to take a string as route and a "lambda" as a request handler. &lt;code&gt;((name route) (age form))&lt;/code&gt; means there has a parameter &lt;code&gt;name&lt;/code&gt; is taken from &lt;code&gt;route&lt;/code&gt; and a parameter &lt;code&gt;age&lt;/code&gt; is taken from &lt;code&gt;form&lt;/code&gt;. And &lt;code&gt;(format "Hello, ~a. Your age is ~a." name age)&lt;/code&gt; is the body of the handler function.&lt;/p&gt;

&lt;p&gt;Everything looks good! But we have no idea how to make it, not yet ;). So I'm going to show you how to build up this macro step by step, as a tutorial.&lt;/p&gt;

&lt;p&gt;First, we have to ensure the target. I don't want to work with original Racket HTTP lib because I never try it, so I pick &lt;a href="//github.com/Junker/routy"&gt;routy&lt;/a&gt; as a routing solution. A &lt;a href="//github.com/Junker/routy"&gt;routy&lt;/a&gt; equivalent solution would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request/param&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="ss"&gt;'name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-form/get&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt; &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;WARNING: There has no function named &lt;code&gt;http-form/get&lt;/code&gt;, but let's assume we have such program to focus on the topic of the article: &lt;strong&gt;macro&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can notice that there was no &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt; in &lt;code&gt;lambda&lt;/code&gt; now. But have to get it by using &lt;code&gt;request/param&lt;/code&gt; and &lt;code&gt;http-form/get&lt;/code&gt;. But there also has the same pattern, the route! To build up macro, we need the following code at the top of the file &lt;code&gt;macro.rkt&lt;/code&gt; first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;for-syntax&lt;/span&gt; &lt;span class="nv"&gt;racket/base&lt;/span&gt; &lt;span class="nv"&gt;racket/syntax&lt;/span&gt; &lt;span class="nv"&gt;syntax/parse&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we get our first macro definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;route:str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="ss"&gt;'body&lt;/span&gt;&lt;span class="p"&gt;)))]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;; output: '(routy/get "/user/:name" (lambda (req params) 'body))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at each line, first, we have &lt;code&gt;define-syntax&lt;/code&gt;, which is like &lt;code&gt;define&lt;/code&gt; but define a macro. It contains two parts, &lt;strong&gt;name&lt;/strong&gt; and &lt;code&gt;syntax-parse&lt;/code&gt;. The name part was &lt;code&gt;(get stx)&lt;/code&gt;, so the macro called &lt;code&gt;get&lt;/code&gt;, with a syntax object &lt;code&gt;stx&lt;/code&gt;. The &lt;code&gt;syntax-parse&lt;/code&gt; part was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;route:str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="ss"&gt;'body&lt;/span&gt;&lt;span class="p"&gt;)))])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;syntax-parse&lt;/code&gt; part works on the syntax object, so it's arguments are a syntax object and patterns! Yes, patterns! It's ok to have multiple patterns like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;multiple-patterns?&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;multiple-patterns?&lt;/span&gt; &lt;span class="nv"&gt;s:str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;ok-str&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;multiple-patterns?&lt;/span&gt; &lt;span class="nv"&gt;s:id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;ok-id&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;multiple-patterns?&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;; output: 'ok-str&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;multiple-patterns?&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;; output: 'ok-id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we want to add handler into &lt;code&gt;get&lt;/code&gt;, to reduce the complexity, we introduce another feature: &lt;code&gt;define-syntax-class&lt;/code&gt;. The code would become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;handler-lambda&lt;/span&gt;
    &lt;span class="nt"&gt;#:literals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*:id&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;clause&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt;
      &lt;span class="nv"&gt;application&lt;/span&gt;
      &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nv"&gt;clause&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nv"&gt;arg*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;route:str&lt;/span&gt; &lt;span class="nv"&gt;handler:handler-lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)))]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we compare &lt;code&gt;syntax-parse&lt;/code&gt; block, we add &lt;code&gt;handler:handler-lambda&lt;/code&gt; and &lt;code&gt;handler.application&lt;/code&gt; here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;route:str&lt;/span&gt; &lt;span class="nv"&gt;handler:handler-lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nv"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)))]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we use a &lt;code&gt;define-syntax-class&lt;/code&gt; in a higher-level syntax. &lt;code&gt;handler:handler-lambda&lt;/code&gt; just like &lt;code&gt;route:str&lt;/code&gt;, the only differences are their pattern. &lt;code&gt;route:str&lt;/code&gt; always expected a string, &lt;code&gt;handler:handler-lambda&lt;/code&gt; always expected a &lt;code&gt;handler-lambda&lt;/code&gt;. And notice that &lt;code&gt;handler:handler-lambda&lt;/code&gt; would be the same as &lt;code&gt;a:handler-lambda&lt;/code&gt;, just have to use &lt;code&gt;a&lt;/code&gt; to refer to that object. But better give it a related name.&lt;/p&gt;

&lt;p&gt;Then dig into &lt;code&gt;define-syntax-class&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;handler-lambda&lt;/span&gt;
  &lt;span class="nt"&gt;#:literals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*:id&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;#:with&lt;/span&gt;
    &lt;span class="nv"&gt;application&lt;/span&gt;
    &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;arg*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;define-syntax-class&lt;/code&gt; allows us add some &lt;code&gt;stxclass-option&lt;/code&gt;, for example: &lt;code&gt;#:literals (lambda)&lt;/code&gt; marked &lt;code&gt;lambda&lt;/code&gt; is not a pattern variable, but a literal pattern. The body of &lt;code&gt;define-syntax-class&lt;/code&gt; is a pattern, which takes a pattern and some &lt;code&gt;pattern-directive&lt;/code&gt;. The most important &lt;code&gt;pattern-directive&lt;/code&gt; was &lt;code&gt;#:with&lt;/code&gt;, which stores how to transform this pattern, it takes a &lt;code&gt;syntax-pattern&lt;/code&gt; and an &lt;code&gt;expr&lt;/code&gt;, as you already saw, this is usage: &lt;code&gt;handler.application&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The interesting part was &lt;code&gt;...&lt;/code&gt; in the pattern, it means zero to many patterns. A little tip makes such variables with a suffix &lt;code&gt;*&lt;/code&gt; like &lt;code&gt;arg*&lt;/code&gt; and &lt;code&gt;clause*&lt;/code&gt; at here.&lt;/p&gt;

&lt;p&gt;Now take a look at usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;; output: '(routy/get "/user/:name" (lambda (req params) ((lambda (name age) (format "Hello, ~a. Your age is ~a." name age)) name age)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some issues leave now, since we have to distinguish &lt;code&gt;route&lt;/code&gt; and &lt;code&gt;form&lt;/code&gt;, current pattern of &lt;code&gt;handler-lambda&lt;/code&gt; is not enough. The &lt;code&gt;handler-lambda.application&lt;/code&gt; also incomplete, we need&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request/param&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="ss"&gt;'name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-form/get&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt; &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt;
            &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;right now.&lt;/p&gt;

&lt;p&gt;To decompose the abstraction, we need another &lt;code&gt;define-syntax-class&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;argument&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg:id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt; &lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request/param&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="ss"&gt;'arg&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg:id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt; &lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-form/get&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'arg&lt;/span&gt;&lt;span class="p"&gt;))]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;handler-lambda&lt;/span&gt;
  &lt;span class="nt"&gt;#:literals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*:argument&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nt"&gt;#:with&lt;/span&gt;
    &lt;span class="nv"&gt;application&lt;/span&gt;
    &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two changes, replace &lt;code&gt;lambda&lt;/code&gt; with &lt;code&gt;let&lt;/code&gt; in &lt;code&gt;handler-lambda.application&lt;/code&gt;(it's more readable), and use &lt;code&gt;argument&lt;/code&gt; syntax type instead of &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;argument&lt;/code&gt; has two patterns, &lt;code&gt;arg:id (~literal route)&lt;/code&gt; and &lt;code&gt;arg:id (~literal form)&lt;/code&gt; to match &lt;code&gt;(x route)&lt;/code&gt; and &lt;code&gt;(x form)&lt;/code&gt;. Notice that &lt;code&gt;#:literals (x)&lt;/code&gt; and &lt;code&gt;(~literal x)&lt;/code&gt; has the same ability, just pick a fit one. &lt;code&gt;symbol-&amp;gt;string&lt;/code&gt; converts an atom to a string, here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;; output: "x"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;; output: '(routy/get "/user/:name" (lambda (req params) (let ((name (request/param params 'name)) (age (http-form/get req (symbol-&amp;gt;string 'age)))) (format "Hello, ~a. Your age is ~a." name age))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manually pretty output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request/param&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="ss"&gt;'name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-form/get&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'age&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;With make up this tutorial, I learn a lot of macro tips in Racket that I don't know before. I hope you also enjoy this, also hope you can use everything you learn from here to create your helpful macro. Have a nice day.&lt;/p&gt;

&lt;h3&gt;
  
  
  End up, all code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight racket"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="nv"&gt;racket&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;for-syntax&lt;/span&gt; &lt;span class="nv"&gt;racket/base&lt;/span&gt; &lt;span class="nv"&gt;racket/syntax&lt;/span&gt; &lt;span class="nv"&gt;syntax/parse&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define-syntax&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;argument&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg:id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt; &lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request/param&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt; &lt;span class="ss"&gt;'arg&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg:id&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;~literal&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt; &lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;arg&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-form/get&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="ss"&gt;'arg&lt;/span&gt;&lt;span class="p"&gt;))]))&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-syntax-class&lt;/span&gt; &lt;span class="nv"&gt;handler-lambda&lt;/span&gt;
    &lt;span class="nt"&gt;#:literals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*:argument&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nt"&gt;#:with&lt;/span&gt;
      &lt;span class="nv"&gt;application&lt;/span&gt;
      &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arg*&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;get-it&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nv"&gt;clause*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;syntax-parse&lt;/span&gt; &lt;span class="nv"&gt;stx&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;route:str&lt;/span&gt; &lt;span class="nv"&gt;handler:handler-lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;#'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;routy/get&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;req&lt;/span&gt; &lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)))]))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="s"&gt;"/user/:name"&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="nv"&gt;form&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"Hello, ~a. Your age is ~a."&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>metaprogramming</category>
      <category>racket</category>
    </item>
    <item>
      <title>NOTE: bounded polymorphism</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Fri, 24 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/note-bounded-polymorphism-3meh</link>
      <guid>https://forem.com/dannypsnl/note-bounded-polymorphism-3meh</guid>
      <description>&lt;p&gt;Bounded polymorphism refers to existential quantifiers(∃), restricted to range over types of bound type. To understand it only needs a few examples. Let’s start! Take a look at the following program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;numSort&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Num&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Num a&lt;/code&gt; is how we represent the bounded polymorphism in &lt;strong&gt;Haskell&lt;/strong&gt; , the definition of &lt;code&gt;Num&lt;/code&gt; was &lt;code&gt;class Num b where&lt;/code&gt;(Hoogle shows &lt;code&gt;a&lt;/code&gt;, just prevent to confuse reader don’t familiar with &lt;strong&gt;Haskell&lt;/strong&gt; ) could read as &lt;strong&gt;a type &lt;code&gt;b&lt;/code&gt; is an instance of class &lt;code&gt;Num&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;numSort&lt;/code&gt; takes &lt;code&gt;[a]&lt;/code&gt; only if &lt;code&gt;a&lt;/code&gt; is an instance of &lt;code&gt;Num&lt;/code&gt;. Now we could run down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;numSort&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;numSort&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is really a powerful feature(and you don’t need to use &lt;strong&gt;Haskell&lt;/strong&gt; for this, &lt;strong&gt;Java&lt;/strong&gt; also has this feature), consider the old way to do &lt;code&gt;List&amp;lt;A&amp;gt;&lt;/code&gt; to &lt;code&gt;List&amp;lt;B&amp;gt;&lt;/code&gt;, and unfortunately solution was to copy each element in the list.&lt;/p&gt;

</description>
      <category>plt</category>
      <category>language</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Type as Constraint: Why we need more type?</title>
      <dc:creator>林子篆</dc:creator>
      <pubDate>Thu, 16 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/dannypsnl/type-as-constraint-why-we-need-more-type-5bpb</link>
      <guid>https://forem.com/dannypsnl/type-as-constraint-why-we-need-more-type-5bpb</guid>
      <description>&lt;p&gt;For me, programming was about how to map my mind to the world; from this view, it probably shows why I tend to use statically typed language. A strong model could ensure more people won't misunderstand our purpose. This article was going to show some strategy to promise the thing works in our mind won't be broken by others accident.&lt;/p&gt;

&lt;p&gt;Now consider a situation, we had a list of something and we just sort it and we want to do binary-search with it. A subtle problem was we were hard to ensure the list was sorted. In the language such as Python or C, we had to promise this by ourselves. So we insert &lt;code&gt;assert(sorted(list))&lt;/code&gt; into our program like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;p.s. &lt;a href="https://www.programiz.com/python-programming/assert-statement"&gt;More assertion in Python&lt;/a&gt;, I'm not a Python master. I have to say.&lt;/p&gt;

&lt;p&gt;And then we feel the program became slower. Because we were so smart, we distinguish debug and release environment, there were no assertions in release mode. Now everything runs good, right? Well, if you wrote some programs with verified data, that's ok. But what if the &lt;code&gt;lst&lt;/code&gt; came from the user input? It probably would break, or let's be honest, it would break. So remove checking from there shouldn't happen. But many languages cannot ensure it, we have to take responsibility.&lt;/p&gt;

&lt;p&gt;With wrapping, we can make it a little bit better. We can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;SortedList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// sorting&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SortedList&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SortedList&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BinarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="n"&gt;SortedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// you know, just ignore how we get the element&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;sortedLst&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BinarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sortedLst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is a weak promise, anyone can just use &lt;code&gt;SortedList{lst: lst}&lt;/code&gt; to break it, but better than no promise. But already easier to find out in code review.&lt;/p&gt;

&lt;p&gt;The problem was this is not just easy to break, but it also didn't promise enough information for us. What if we modify the list before we use &lt;code&gt;BinarySearch&lt;/code&gt;? This promise required some human work to check it. Now we want a more improved version. A promise that cannot be violated and doesn't need human work to check the mechanism. As usual, I would use pseudo-code(to get more information, ref to &lt;a href="https://dannypsnl.github.io/docs/cs/infinite-type/"&gt;my another article&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sort[T: comparable](list: List[T]): Output
where
  Output = List[T] // type alias
  Output &amp;lt;: sorted // now we know the result type was a subtype of `sorted`
{
  // sorting
}

binary_search[T: comparable](list: List[T] &amp;lt;: sorted): T {
  // do something and get the answer
  return element;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then we can use them like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sorted_list: List[int] = sort(list);
_: int = binary_search(sorted_list); // `_` explicitly ignore value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important thing is when we do operations that do not fit trait &lt;code&gt;sorted&lt;/code&gt; the program work as usual but the compiler won't think the value was &lt;code&gt;sorted&lt;/code&gt; anymore, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sorted_list: List[int] = sort(list);
sorted_list.push(3); // add element
_: int = binary_search(sorted_list);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it won't get compiled, because the type mismatching, we can do &lt;code&gt;push&lt;/code&gt; on &lt;code&gt;List[int]&lt;/code&gt;, but after that &lt;code&gt;sorted_list&lt;/code&gt; won't belong to &lt;code&gt;sorted&lt;/code&gt; trait anymore. Do you probably think why not make another type? Because although we, of course, can do that, it would be bad modeling in another case, when we just sort a list and later keep doing something on it and don't care about it's sorted or not til next sort, create another type would let we must keep converting type manually, which violate our spirit! Now back, &lt;code&gt;sorted&lt;/code&gt; trait modeled the situation very well, we only have to give tag, the compiler checks the rest. We still have checking, we have to ensure the part need to do &lt;code&gt;binary_search&lt;/code&gt; get &lt;code&gt;List[T] &amp;lt;: sorted&lt;/code&gt;, but this is better than adding assertion everywhere. I hope you have a nice day and thanks for the read.&lt;/p&gt;

</description>
      <category>plt</category>
      <category>language</category>
    </item>
  </channel>
</rss>
