{-# LANGUAGE GADTs, ExistentialQuantification, TypeFamilies,
FlexibleContexts #-}
-- Homework assignment: complete this interpreter
module Interp where
-- No scoping errors for this interpreter
-- No typing errors
-- Uses type families
-- Tagless interpreter that uses a first-order rep
-- of function values (i.e. closures) instead of
-- higher-order rep.
-- type of interp is Env g -> Exp g t -> Result t
-- where the result of a function type is a closure.
type family Result t
type instance Result Int = Int
type instance Result (a -> b) = Closure a b
data Var g t where
Z :: Var (g, t) t
S :: Var g t -> Var (g, t') t
-- An environment datatype so that we can ensure that
-- we can print out closures. (i.e. each value added
-- to the Env must be Showable.)
data Env g where
ENil :: Env ()
ECons :: Show (Result t) => Env g -> Result t -> Env (g,t)
-- A closure is an environment paired with a term w/ 1 free variable.
data Closure a b where
Clos :: Show (Result a) => Env g -> Exp (g, a) b -> Closure a b
data Exp g t where
Var :: Var g t -> Exp g t
Lit :: Int -> Exp g Int
Lam :: (Show (Result a)) => Exp (g, a) b -> Exp g (a -> b)
App :: Exp g (a -> b) -> Exp g a -> Exp g b
---------------------
-- Show instances
instance (Show (Var g t)) where
show Z = "Z"
show (S x) = "S " ++ show x
instance Show (Exp g n) where
show (Var lt) = "(Var " ++ show lt ++ ")"
show (Lit i) = "(Lit " ++ show i ++ ")"
show (Lam t) = "(Lam " ++ show t ++ ")"
show (App t u) = "(App " ++ show t ++ " " ++ show u ++ ")"
instance Show (Closure a b) where
show (Clos e t) = "(Clos " ++ show e ++ "**" ++ show t ++ ")"
instance Show (Env g) where
show ENil = "()"
show (ECons g r) = "(" ++ show g ++ "," ++ show r ++ ")"
---------------------
-- Interpreter
interp :: Show (Result t) => Env g -> Exp g t -> Result t
interp = undefined
{- Fill this part in -}
-------------------------
-- examples
e0 :: Exp () (Int -> Int)
e0 = Lam (Var Z)
t0 = interp ENil (App e0 (Lit 2))
-- doesn't type check
-- t1 = interp nil (Var (s z))
-- doesn't type check
-- t2 = interp () (App (Lit 2) (Lit 3))
e1 :: Exp ((), Int) ((Int -> Int) -> Int)
e1 = Lam (App (Var Z) (Var (S Z)))
e2 :: Exp () (Int -> (Int -> Int) -> Int)
e2 = Lam e1
t3 = interp ENil (App e2 (Lit 3))
-- Once you have a Closure, what do you do with it?
apply :: Show (Result b) => Closure a b -> Result a -> Result b
apply (Clos e t) ra = interp (ECons e ra) t