Last active
September 21, 2019 19:04
-
-
Save pedrominicz/b15108e2e3a7c164cfdba0c0f37ba723 to your computer and use it in GitHub Desktop.
Simply Typed Lambda Calculus with GADTs (doodle made while reading a SO answer).
This file contains 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
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE GADTs #-} | |
{-# LANGUAGE StandaloneDeriving #-} | |
{-# LANGUAGE TypeOperators #-} | |
-- https://stackoverflow.com/questions/27831223/simply-typed-lambda-calculus-with-failure-in-haskell | |
-- https://www.youtube.com/watch?v=6snteFntvjM | |
module General where | |
data Elem as a where | |
EZ :: Elem (x:xs) x | |
ES :: Elem xs x -> Elem (y:xs) x | |
deriving instance Show (Elem as a) | |
data Expr as a where | |
Ref :: Elem as a -> Expr as a | |
Lam :: Expr (a:as) b -> Expr as (a -> b) | |
App :: Expr as (a -> b) -> Expr as a -> Expr as b | |
Num :: Integer -> Expr as Integer | |
Bool :: Bool -> Expr as Bool | |
deriving instance Show (Expr as a) | |
data Value a where | |
Closure :: Env as -> Expr as (a -> b) -> Value (a -> b) | |
Number :: Integer -> Value Integer | |
Boolean :: Bool -> Value Bool | |
deriving instance Show (Value a) | |
data Env as where | |
Empty :: Env '[] | |
Cons :: Value a -> Env as -> Env (a:as) | |
deriving instance Show (Env as) | |
eval :: Expr '[] a -> Value a | |
eval expr = eval' Empty expr | |
where eval' :: Env as -> Expr as a -> Value a | |
eval' env (Ref x) = lookup' x env | |
eval' env (Lam x) = Closure env (Lam x) | |
eval' env (App x y) = apply (eval' env x) (eval' env y) | |
eval' _ (Num x) = Number x | |
eval' _ (Bool x) = Boolean x | |
apply :: Value (a -> b) -> Value a -> Value b | |
apply (Closure env (Lam body)) x = eval' (Cons x env) body | |
apply _ _ = undefined | |
lookup' :: Elem as a -> Env as -> Value a | |
lookup' EZ (Cons x _) = x | |
lookup' (ES x) (Cons _ xs) = lookup' x xs | |
-- eval $ App (Lam (Ref EZ)) (App (Lam (Num 10)) (Bool False)) | |
-- eval $ App (Lam (App (Ref EZ) (Num 10))) (Lam (Ref EZ)) | |
-- eval $ Lam (Ref EZ) | |
s :: Expr as ((a -> b -> c) -> (a -> b) -> a -> c) | |
s = Lam (Lam (Lam (App (App (Ref (ES (ES EZ))) (Ref EZ)) (App (Ref (ES EZ)) (Ref EZ))))) | |
k :: Expr as (a -> b -> a) | |
k = Lam (Lam (Ref (ES EZ))) | |
i :: Expr as (a -> a) | |
i = Lam (Ref EZ) | |
-- eval $ (App (App s k) k) | |
-- eval $ (App (App (App s k) k) (Num 10)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment