{-# LANGUAGE GADTs #-}
-- Types: read, understand and extend Haskell programs which use advanced type system features
-- Types.Class: type classes, newtypes, deriving, ...
-- Types.GADT: (generalised) algebraic datatypes & type families
-- Types.HOT: functors, monads and monad transformers
__import__ Control.Monad (liftM2)
__data__ Expr t __where__
C :: Char -> Expr Char
I :: Int -> Expr Int
(**:@**) :: Expr (a -> b) -> Expr a -> Expr b
Nil :: Expr [a]
Cons :: Expr (a -> [a] -> [a])
Replicate :: Expr (Int -> a -> [a])
Length :: Expr ([a] -> Int)
-- Added later
V :: Name -> Expr String
__type__ Name = Int
eval :: Expr t -> t
eval (C c) = c
eval (I i) = i
eval (f **:@** x) = (eval f) (eval x)
eval Nil = []
eval Cons = (**:**)
eval Replicate = replicate
eval Length = length
test = eval (Replicate **:@** (I 5) **:@** Nil)
stringLit :: String -> Expr String
stringLit = foldr (\x e -> Cons **:@** C x **:@** e) Nil
-- Added later:
eval2 :: (Name -> Maybe String) -> Expr t -> Maybe t
eval2 lookup (V v) = lookup v
eval2 l (C c) = Just c
eval2 l (I i) = Just i
eval2 l (f **:@** x) = liftM2 ($) (eval2 l f) (eval2 l x)
eval2 l Nil = Just []
eval2 l Cons = Just (**:**)
eval2 l Replicate = Just replicate
eval2 l Length = Just length
-- Changes:
-- * new constructor for Int-labelled variables
-- * Monadic (to handle variable lookup failure)
-- * eval2 has a new case for the variables
test2 = eval2 (const (Just "hej")) (Replicate **:@** (Length **:@** (V 1)) **:@** V 1)
----------------------------------------------------------------