Last active
June 7, 2018 12:32
-
-
Save alogic0/32bb5fa153d8ca93e5176e0bc86e92ce to your computer and use it in GitHub Desktop.
The Hindley-Milner's algorithm of unification of two types. If they could be unified, of course.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module HindleyMilner where | |
import Control.Applicative ((<|>)) | |
import Control.Monad (guard) | |
import Data.Maybe (fromJust) | |
type Symb = String | |
infixr 3 :-> | |
data Type | |
= TVar Symb | |
| Type :-> Type | |
deriving (Eq, Show) | |
subst :: [(Type,Type)] -> Type -> Maybe Type | |
subst lst t = | |
case t of | |
(t1 :-> t2) -> (:->) <$> (subst lst t1) <*> (subst lst t2) | |
_ -> lookup t lst <|> Just t | |
freeVars :: Type -> [Symb] | |
freeVars (TVar x) = [x] | |
freeVars (t1 :-> t2) = freeVars t1 ++ freeVars t2 | |
unify :: Type -> Type -> Maybe [(Type, Type)] | |
unify va@(TVar _) vb@(TVar _) = | |
if va == vb | |
then Just [] | |
else Just [(va, vb)] | |
unify va@(TVar a) t | |
| a `elem` freeVars t = Nothing | |
| otherwise = Just [(va,t)] | |
unify t@(_ :-> _) va@(TVar _) = unify va t | |
unify (s1 :-> s2) (t1 :-> t2) = do | |
uni2 <- unify s2 t2 | |
s1' <- subst uni2 s1 | |
t1' <- subst uni2 t1 | |
uniNew <- unify s1' t1' | |
return $ uni2 ++ uniNew | |
-- Tests | |
{- | |
seqSubst lst e = foldl (\e s -> fromJust $ subst [s] e) e lst | |
test a b = unify a b >>= \lst -> return $ seqSubst lst a == seqSubst lst b | |
test (TVar "a" :-> TVar "b" :-> TVar "c") (TVar "d" :-> TVar "d") | |
test (TVar "b" :-> TVar "b") (((TVar "g" :-> TVar "d") :-> TVar "e") :-> TVar "a" :-> TVar "d") | |
test (TVar "a" :-> TVar "b" :-> TVar "a") (TVar "g" :-> TVar "d") | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To beautify types and write them like in usual Haskell, the next mess of code is produced. To work it requires
Place this file in the same directory as
HindleyMilner.hs
, run ghci there and load the code>:l TypeParser.hs
then copy and paste the strings with
test
commands from the end of file. Now you cantest
various simple types for possible unification. Look at the resulting type and the required substitutions for the originals to mutate into it. The order of substitutions from left to right.TypeParser.hs