Skip to content

Instantly share code, notes, and snippets.

@nponeccop
Created January 20, 2017 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nponeccop/7ba833db625fed06cb449cdfbd538be1 to your computer and use it in GitHub Desktop.
Save nponeccop/7ba833db625fed06cb449cdfbd538be1 to your computer and use it in GitHub Desktop.
Minimal Hindley Milner type checker example using HNC Unifier
{-# LANGUAGE LambdaCase #-}
import Unifier.Unifier
import Unifier.Restricted
import Control.Monad.Identity
import Control.Unification (freeVar, freshen, applyBindings)
import Control.Unification.IntVar
import Control.Monad.Trans
import qualified Data.Map as M
data Expression = Atom String | App Expression Expression
check :: Lib -> Expression -> Stack Type
check lib = \case
Atom a -> look lib a
App a b -> do
UTerm (TT [argA, res]) <- check lib a
argB <- check lib b
unify argA argB
return res
-- Boilerplate
type Stack = WithExcept (WithEnv Identity)
type Lib = M.Map String Type
run x = runIdentity $ runIntBindingT x
look :: Lib -> String -> Stack Type
look b a = case M.lookup a b of Just a -> freshen a
runCheck x = run $ runErrorT2 $ do
lib <- lift makeLib
check lib x >>= applyBindings
-- Examples
makeLib :: WithEnv Identity Lib
makeLib = do
a <- UVar <$> freeVar
b <- UVar <$> freeVar
return $ UTerm <$> M.fromList
[ ("id", TT [a, a])
, ("one", T "Int")
, ("const", TT [a, UTerm $ TT [b, a]])
]
check1 = Atom "one"
check2 = App (Atom "const") (Atom "one")
check3 = App (App (Atom "const") (Atom "one")) (Atom "id")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment