Created
July 3, 2012 13:56
-
-
Save fumieval/3039853 to your computer and use it in GitHub Desktop.
オレオレ型推論
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
import qualified Data.Map as Map | |
import qualified Data.Set as Set | |
import Data.List (partition) | |
import Control.Arrow (first, second) | |
import Control.Applicative | |
infixr 9 :-> | |
infixl 8 >$ | |
type Name = String | |
data Type = Var Name | Type :-> Type | Rigid Name | Any deriving (Show, Eq, Ord, Read) | |
data TypeError = Conflict Type Type | Infinite Type deriving (Show) | |
subst :: Name -> Type -> Type -> Type | |
subst v t (x :-> y) = subst v t x :-> subst v t y | |
subst v t (Var v') | v == v' = t | |
subst _ _ x = x | |
corresponds :: Type -> Type -> Either TypeError [(Name, Type)] | |
corresponds Any x = Right [] | |
corresponds (Rigid x) (Rigid x') | x == x' = Right [] | |
corresponds (Rigid x) t = Left $ Conflict (Rigid x) t | |
corresponds (Var x) (Var x') | x == x' = Right [] | |
corresponds (Var x) t = Right [(x, t)] | |
corresponds (s :-> t) (u :-> v) = (,) <$> cs <*> (foldr (uncurry subst) t <$> cs >>= flip corresponds v) >>= union | |
where | |
union (xs, ys) = case (partition $ (==1) . length . snd) | |
$ map (second Set.toList) | |
$ Map.toList $ Map.fromListWith (Set.union) | |
$ map (second Set.singleton) $ xs ++ ys of | |
(_, (_, (x:y:_)):_) -> Left $ Conflict x y | |
(xs, _) -> Right $ map (second head) xs | |
cs = corresponds s u | |
corresponds x y = Left $ Conflict y x | |
apply :: Type -> Type -> Either TypeError Type | |
apply (a :-> b) x = foldr (uncurry subst) b <$> corresponds a x | |
apply x y = Left $ Conflict (y :-> Any) x | |
typeS = (Var "a" :-> Var "b" :-> Var "c") :-> (Var "a" :-> Var "b") :-> Var "a" :-> Var "c" | |
typeK = Var "a" :-> Var "b" :-> Var "a" | |
typeI = Var "a" :-> Var "a" | |
(>$) :: Type -> Type -> Type | |
(>$) = (either (error.show) id .) . apply |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment