Last active
July 18, 2022 16:36
-
-
Save pedrominicz/78994453ab65fb4c5a9a6b25c08fff89 to your computer and use it in GitHub Desktop.
Simply Typed Lambda Calculus with Type Checker (doodle made while reading a SO answer).
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 Typed where | |
-- https://stackoverflow.com/questions/27831223/simply-typed-lambda-calculus-with-failure-in-haskell | |
import Safe (atMay) | |
data Type | |
= LamT Type Type | |
| NumT | |
deriving (Eq, Show) | |
data Term | |
= Var Int | |
| Lam Type Term | |
| App Term Term | |
| Num Integer | |
deriving Show | |
check :: [Type] -> Term -> Maybe Type | |
check env (Var x) = atMay env x | |
check env (Lam a b) = LamT a <$> check (a:env) b | |
check env (App f a) = do | |
f <- check env f | |
a <- check env a | |
case f of | |
LamT a' b | a == a' -> return b | |
_ -> Nothing | |
check _ (Num _) = return NumT | |
data Value | |
= Closure [Value] Term | |
| Number Integer | |
deriving Show | |
eval :: Term -> Maybe Value | |
eval t = go [] t <$ check [] t | |
where | |
go :: [Value] -> Term -> Value | |
go env (Var x) = env !! x | |
go env (Lam t x) = Closure env (Lam t x) | |
go env (App x y) = apply (go env x) (go env y) | |
go _ (Num x) = Number x | |
apply :: Value -> Value -> Value | |
apply (Closure env (Lam _ body)) x = go (x:env) body | |
apply _ _ = undefined | |
s :: Term | |
s = Lam (LamT NumT (LamT NumT NumT)) (Lam (LamT NumT NumT) (Lam NumT (App (App (Var 2) (Var 0)) (App (Var 1) (Var 0))))) | |
k :: Term | |
k = Lam NumT (Lam NumT (Var 1)) | |
i :: Term | |
i = Lam NumT (Var 0) | |
main :: IO () | |
main = do | |
print . eval $ App (Lam NumT (Var 0)) (App (Lam NumT (Num 10)) (Num 0)) | |
print . eval $ App (Lam (LamT NumT NumT) (App (Var 0) (Num 10))) (Lam NumT (Var 0)) | |
print . eval $ Lam NumT (Var 0) | |
print . eval $ App (Lam NumT (Var 0)) (Num 10) | |
print . eval $ App (App s k) i | |
print . eval $ App (App (App s k) i) (Num 10) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment