25.10.2015 Views

Write You a Haskell Stephen Diehl

1kEcQTb

1kEcQTb

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Γ, x : τ = (Γ\x) ∪ {x : τ}<br />

Operations over the context are simply the usual Set operations on the underlying map.<br />

extend :: TypeEnv -> (Var, Scheme) -> TypeEnv<br />

extend (TypeEnv env) (x, s) = TypeEnv $ Map.insert x s env<br />

Inference Monad<br />

All our logic for type inference will live inside of the Infer monad. Which is a monad transformer stack<br />

of ExcpetT + State, allowing various error reporting and statefully holding the fresh name supply.<br />

type Infer a = ExceptT TypeError (State Unique) a<br />

Running the logic in the monad results in either a type error or a resulting type scheme.<br />

runInfer :: Infer (Subst, Type) -> Either TypeError Scheme<br />

runInfer m = case evalState (runExceptT m) initUnique of<br />

Left err -> Left err<br />

Right res -> Right $ closeOver res<br />

Substitution<br />

Two operations that will perform quite a bit are querying the free variables of an expression and applying<br />

substitutions over expressions.<br />

fv(x) = x<br />

fv(λx.e) = fv(e) − {x}<br />

fv(e 1 e 2 ) = fv(e 1 ) ∪ fv(e 2 )<br />

Likewise the same pattern applies for type variables at the type level.<br />

ftv(α) = {α}<br />

ftv(τ 1 → τ 2 ) = ftv(τ 1 ) ∪ ftv(τ 2 )<br />

ftv(Int) = ∅<br />

ftv(Bool) = ∅<br />

ftv(∀x.t) = ftv(t) − {x}<br />

Substitutions over expressions apply the substitution to local variables, replacing the named subexpression<br />

if matched. In the case of name capture a fresh variable is introduced.<br />

83

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!