Advertisement
elvecent

typed lambda haskell

Nov 19th, 2017
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List
  2.  
  3. main = return ()
  4.  
  5. main' (ctx,bs) = do
  6.                 line <- getLine
  7.                 putStrLn line
  8.                 main' (ctx,bs)
  9.  
  10. data Type = Base String | Arr Type Type deriving Eq
  11.  
  12. instance Show Type where
  13.   show (Base str) = str
  14.   show (Arr t1 t2) = show t1 ++ "->" ++ (show t2)
  15.  
  16. type Context = [(String, Type)]
  17.  
  18. addToCtx :: Context ->
  19.             String -> Type ->
  20.             Either String Context
  21. addToCtx [] v t = Right [(v,t)]
  22. addToCtx vs v t = if (v `elem` (map fst vs))
  23.                   then Left $ "Variable " ++ v ++ " is already in context"
  24.                   else Right $ (v,t) : vs
  25.                  
  26. getFromCtx :: Context ->
  27.               String ->
  28.               Either String (String, Type)
  29. getFromCtx [] v = Left $ "Variable " ++ v ++ " is not in context"
  30. getFromCtx (v:vs) v' = if (fst v == v')
  31.                        then Right v
  32.                        else getFromCtx vs v'
  33.                      
  34. data Term = Var String
  35.          | App Term Term
  36.          | Lambda String Term
  37.          
  38. unlambda :: Term -> ([String], Term)
  39. unlambda (Lambda x l) = (x : vars, rest)
  40.                        where (vars, rest) = unlambda l
  41. unlambda l = ([], l)
  42.          
  43. instance Show Term where
  44.  show (Var x) = x
  45.  show (App l1 (l@(App l2 l3))) = show l1 ++ " (" ++ (show l) ++ ")"
  46.  show (App l1 l2) = show l1 ++ " " ++ (show l2)
  47.  show (Lambda x l) = "(" ++ "λ" ++ args ++ "." ++ (show body) ++ ")"
  48.                      where (vars, body) = unlambda (Lambda x l)
  49.                            args = concat $ intersperse " " vars
  50.                      
  51. data Expr = VarDecl String Type
  52.          | VarDef String Type Term
  53.          | Print Term
  54.          | Eval Term
  55.          
  56. unright :: Either a b -> b
  57. unright (Right x) = x
  58.          
  59. funcMismatch :: Term -> Type -> Type -> String
  60. funcMismatch arg targ tf = "Argument " ++ show arg ++ " : " ++ (show targ)
  61.                           ++ " doesn't match " ++ (show tf)
  62.          
  63. check :: Context -> Term -> Type -> Either String ()
  64. check ctx
  65.      (Lambda x fx)
  66.      (Arr t1 t2) = check ctx (Var x) t1 >> check ctx fx t2
  67. check _ (Lambda _ _) _ = Left "Lambdas can't have non-arrow types"
  68. check ctx
  69.      term
  70.      t = typeTerm ctx term >>=
  71.                       (\t' -> if t == t'
  72.                              then Right ()
  73.                              else Left $ show term ++ " : " ++ (show t') ++
  74.                                           ", expected " ++ (show t))
  75.                                      
  76.  
  77. typeTerm :: Context -> Term -> Either String Type
  78. typeTerm ctx (Var x) = fmap snd $ getFromCtx ctx x
  79. typeTerm ctx (App f x) = (typeTerm ctx f) >>=
  80.                          (\(Arr t1 t2) -> typeTerm ctx x >>=
  81.                                           (\t -> if t == t1
  82.                                                  then Right t2
  83.                                                  else Left $ "Argument type doesn't match function type"))
  84. typeTerm ctx (Lambda _ _) = Left "Unable to type lambdas"
  85.  
  86. type Binding = (String, Term)
  87.  
  88. evalExpr :: Context -> [Binding] -> [String] ->
  89.             Expr ->
  90.             (Context, [Binding], [String])
  91. evalExpr ctx bs ss
  92.          (VarDecl name t) = case addToCtx ctx name t of
  93.                             (Right ctx') -> (ctx',bs,ss)
  94.                             (Left str) -> (ctx,bs,str : ss)
  95. evalExpr ctx bs ss
  96.          (VarDef name t term) = case check ctx term t >>=
  97.                                 (\() -> addToCtx ctx name t) of
  98.                                 (Right ctx') -> (ctx',(name,term):bs,ss)
  99.                                 (Left str) -> (ctx,bs,str : ss)
  100. evalExpr ctx bs ss
  101.          (Print term) = case typeTerm ctx term of
  102.                         (Right t) -> (ctx,bs,(show term ++ " : " ++ (show t)) : ss)
  103.                         (Left str) -> (ctx,bs,str : ss)
  104.                  
  105. evalExprs :: [Expr] -> [String]
  106. evalExprs xs = ext $ foldl (\(c,b,s) e -> evalExpr c b s e) ([],[],[]) xs
  107.                where ext (_,_,s) = reverse s
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement