# Hindley Milner Type System [source: wikipedia] ## Monotypes Monotypes are "concrete" or known types. Monotypes can be: 1. Type constants (`'int` for example), often referred to as $\tau$. 2. parametric types (`'List`). Note that `'List 'int` is an *application* of a *type function* Two monotypes are considered equal if they have the same terms. `'List 'int` == `'List 'int`. ## Polytypes Polytypes (also called a type scheme) are types containing variables bound by for-all qualifiers. $\forall \alpha. \text{List}( \alpha ) \to int$ This type could be used to describe `Len()`, which takes an arbitrary list and returns an int. Polytypes are a generalization of monotypes. $\forall \alpha . \tau$ is an example of a monotype represented as a polytype. ## Context Monotypes require no solving. Polytypes are solved within a *context*. A context is a list of pairs $x : \sigma$ , i.e. assumptions. ## Typing Judgment A typing judgment is formed by combining a context with syntax and types. $\Gamma \vdash e : \sigma $ This judgment means that the expression $e$ has the type $\sigma$ under the context (assumptions) provided in $\Gamma$. Note the similarity to sequent calculus, with the exception that the RHS is not a disjunction. ## Free and bound types In a type $\forall \alpha_1 ... \forall \alpha_n.\tau$ , the forall symbol ($\forall$) is the *quantifier* binding the type variables $\alpha_i$ in the monotype $\tau$. The variables $\alpha_i$ are called *quantified* and any occurrence of a quantified type variable in $\tau$ is called *bound*. All unbound type variables in $\tau$ are called *free*. Put another way, a free type variable in a monotype is a type variable without a $\forall$ quantifier. A type can also be bound by occurring in the context. These contextual variables are basically constant monotypes within the expression. > The presence of both bound and unbound type variables is a bit uncommon in programming languages. Often, all type variables are implicitly treated all-quantified. For instance, one does not have clauses with free variables in [Prolog](https://en.wikipedia.org/wiki/Prolog "Prolog"). Likewise in Haskell, [[note 4]](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#cite_note-10) where all type variables implicitly occur quantified, i.e. a Haskell type `a -> a` means ∀α.α→α![{\displaystyle \forall \alpha .\alpha \rightarrow \alpha }](https://wikimedia.org/api/rest_v1/media/math/render/svg/42801fb803baf2f4bad69c28618eb69ae3234750) here. Related and also very uncommon is the binding effect of the right hand side σ![{\displaystyle \sigma }](https://wikimedia.org/api/rest_v1/media/math/render/svg/59f59b7c3e6fdb1d0365a494b81fb9a696138c36) of the assignments. ## Type Order Structure and decidability is introduced into this system via parametric polymorphism, and levels of generality are determined with substitution rules. A substitution is written as $S = \{\alpha \mapsto \beta\}$. For example, a substitution $S$ that attempts to apply $\text{string}$ to $\alpha$ would be written as $S = \{\alpha \mapsto \text{string} \}$ A type $\sigma '$ is more general than a type $\sigma$ (written as $\sigma' \sqsubseteq \sigma$ ), if some bound variable in $\sigma'$ can be substituted to achieve $\sigma$. We can show that $\forall \alpha.\alpha \to \alpha$ is more general than $\text{string} \to \text{string}$ by applying the above substitution $S$ and achieving $\text{string} \to \text{string}$. When applying substitutions on a parametric type, you must lift the quantifiers (type parameters) to the outer context. A principal type is the *most general* form of a given type expression. # Inference Rules ## Syntax A *predicate* is given in a context, and it one of three forms: 1. $\sigma \sqsubseteq \sigma'$ ($\sigma$ is *more general*, or subsumes, $\sigma'$); 2. $\alpha \notin free(\Gamma)$ ($\alpha$ is not in the set of free variables in the assumption set); 3. $x : \alpha \in \Gamma$ (expression $x$ is assumed to have the type $\alpha$ within $\Gamma$) A judgment is a typing. A premise is a judgment *or* predicate. A conclusion is a judgment. A rule takes the form ((premises/assumptions...) / conclusion) and a name. ## Rules Syntactical: 1. `Var`: accessing a variable or function 2. `App`: a function application with one parameter 3. `Abs`: an *abstraction*, a.k.a. function declaration 4. `Let`: variable declaration Specialization and generalization: 5. `Inst`: instantiates (narrows) a type 6. `Gen`: Quantifies monotype variables not bound in the context. # Algorithm J and W Type Inference Algorithm J is a sort of short-hand that relies on side effects, while Algorithm W is more complicated, formal, and eliminates side effects. # Hindley Milner Problem Set For these problems, write out the solution *and* the sequence of inference rules required to achieve that solution. #### Problem 1: Basic Type Inference Given the following expression, infer the type using the Hindley-Milner type system: $\text{let } \text{id} = \lambda x. x \text{ in } \text{id}$ >[!solution]- Solution For the expression `let id = λx. x in id`: > 1. Assign a type variable to `x`: $x : \alpha$ > 2. The type of `λx. x` is $\alpha \rightarrow \alpha$ > 3. Therefore, the type of `id` is $\forall \alpha. \alpha \rightarrow \alpha$ #### Problem 2: Function Application Infer the type of the following expression: $(\lambda f. \lambda x. f (f x)) (\lambda y. y + 1)$ >[!solution]- Solution > For the expression `(\lambda f. \lambda x. f (f x)) (\lambda y. y + 1)`: > 1. Assign type variables: $( f : \beta \rightarrow \beta ), ( x : \beta )$ > 2. The type of `λf. λx. f (f x)` is $(\beta \rightarrow \beta) \rightarrow (\beta \rightarrow \beta)$ > 3. The type of `λy. y + 1` is $\text{int} \rightarrow \text{int}$ > 4. Substitute and infer the type: $(\text{int} \rightarrow \text{int}) \rightarrow (\text{int} \rightarrow \text{int})$ #### Problem 3: Polymorphic Functions Consider the polymorphic function: $\text{let } \text{compose} = \lambda f. \lambda g. \lambda x. f (g x)$. Infer the type of the `compose` function. >[!solution]- Solution >For the function `let compose = λf. λg. λx. f (g x)`: >1. Assign type variables: $( f : \beta \rightarrow \gamma ), ( g : \alpha \rightarrow \beta ), ( x : \alpha )$ >2. The type of `compose` is $(\beta \rightarrow \gamma) \rightarrow (\alpha \rightarrow \beta) \rightarrow (\alpha \rightarrow \gamma)$ #### Problem 4: Type Generalization Given the expression: $\text{let } \text{const} = \lambda x. \lambda y. x$. Infer the type of `const` and explain the process of type generalization. >[!solution]- Solution For the expression `let const = λx. λy. x` > 1. Assign type variables: $( x : \alpha ), ( y : \beta )$ > 2. The type of `λx. λy. x` is $\alpha \rightarrow (\beta \rightarrow \alpha)$ > 3. Generalize the type: $\forall \alpha \forall \beta. \alpha \rightarrow (\beta \rightarrow \alpha)$ #### Problem 5: Recursive Functions Infer the type of the following recursive function: $\text{let rec } \text{fact} = \lambda n. \text{if } n = 0 \text{ then } 1 \text{ else } n \times \text{fact} (n - 1)$ >[!solution]- Solution For the recursive function `let rec fact = λn. if n = 0 then 1 else n * fact (n - 1)`: > 1. Assign type variables: $( n : \text{int} )$ > 2. The type of `fact` is $( \text{int} \rightarrow \text{int} )$