Last active
May 21, 2018 20:10
-
-
Save i-am-tom/c6531191551425b9e8be703d28dd97ce to your computer and use it in GitHub Desktop.
Simply-Typed Lambda Calculus written in "glorious" "dependent" Haskell.
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 GADTs #-} | |
{-# LANGUAGE LambdaCase #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeInType #-} | |
{-# LANGUAGE TypeOperators #-} | |
module Main (test01, test02, main) where | |
import Data.Kind | |
data Elem :: k -> [k] -> Type where | |
Here :: Elem x (x : xs) | |
There :: Elem x xs -> Elem x (y : xs) | |
data HList :: [Type] -> Type where | |
HNil :: HList '[] | |
HCons :: x -> HList xs -> HList (x ': xs) | |
headHL :: HList (head ': tail) -> head | |
headHL (HCons x _) = x | |
data Expr :: [ProgramType] -> ProgramType -> Type where | |
Ann :: Expr context programType | |
-> ProgramTypeSingleton programType | |
-> Expr context programType | |
Var :: Elem programType context | |
-> Expr context programType | |
App :: Expr context (input :=> output) | |
-> Expr context input | |
-> Expr context output | |
Lam :: ProgramTypeSingleton programType | |
-> Expr (programType : context) bodyType | |
-> Expr context (programType :=> bodyType) | |
data ProgramType | |
= ProgramTypeInt | |
| ProgramType :=> ProgramType | |
data ProgramTypeSingleton :: ProgramType -> Type where | |
ProgramTypeIntSingleton | |
:: ProgramTypeSingleton ProgramTypeInt | |
ProgramTypeFunctionSingleton | |
:: ProgramTypeSingleton input | |
-> ProgramTypeSingleton output | |
-> ProgramTypeSingleton (input :=> output) | |
type family ProgramTypeToType (ptype :: ProgramType) :: Type where | |
ProgramTypeToType ProgramTypeInt | |
= Int | |
ProgramTypeToType (input :=> output) | |
= ProgramTypeToType input | |
-> ProgramTypeToType output | |
type family ContextToTypeList (ptype :: [ProgramType]) :: [Type] where | |
ContextToTypeList '[] | |
= '[] | |
ContextToTypeList (x : xs) | |
= ProgramTypeToType x | |
: ContextToTypeList xs | |
get :: Elem x xs -> HList xs -> x | |
get Here (HCons x _) = x | |
get (There ref) (HCons _ xs) = get ref xs | |
ptypeRefToTypeRef | |
:: Elem programType context | |
-> Elem (ProgramTypeToType programType) | |
(ContextToTypeList context) | |
ptypeRefToTypeRef = \case | |
Here -> Here | |
There ref -> There (ptypeRefToTypeRef ref) | |
eval | |
:: Expr context programType | |
-> HList (ContextToTypeList context) | |
-> ProgramTypeToType programType | |
eval expr context | |
= case expr of | |
Ann expr _ -> | |
eval expr context | |
Var ref -> | |
get (ptypeRefToTypeRef ref) context | |
App f x -> | |
(eval f context) | |
(eval x context) | |
Lam _ body -> | |
\x -> eval body (HCons x context) | |
stlcID :: Expr '[] (ProgramTypeInt :=> ProgramTypeInt) | |
stlcID = Lam ProgramTypeIntSingleton (Var Here) | |
stlcAPPLY | |
:: Expr '[] | |
( (ProgramTypeInt :=> ProgramTypeInt) | |
:=> (ProgramTypeInt :=> ProgramTypeInt) | |
) | |
stlcAPPLY | |
= Lam (ProgramTypeFunctionSingleton ProgramTypeIntSingleton ProgramTypeIntSingleton) | |
$ Lam ProgramTypeIntSingleton (App (Var (There Here)) (Var Here)) | |
test01 = eval stlcAPPLY HNil (+1) 2 | |
test02 = eval stlcID HNil 2 | |
main :: IO () | |
main = do | |
print test01 -- 3 | |
print test02 -- 2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment