Defining project outline

This commit is contained in:
reijix 2023-06-01 09:30:14 +02:00
parent 531ec6e412
commit c11d46956b
6 changed files with 158 additions and 5 deletions

View file

@ -27,3 +27,8 @@ common shared
executable pcf
import: shared
main-is: Main.hs
other-modules:
Syntax
Misc
Evaluator
Typecheck

63
src/Evaluator.hs Normal file
View file

@ -0,0 +1,63 @@
module Evaluator where
import Syntax
import Misc
-- small-step cbn semantics of PCF
eval :: Term -> Term
-- if-then-else
eval (ITE T e2 e3) = e2
eval (ITE F e2 e3) = e3
eval (ITE e1 e2 e3) = ITE (eval e1) e2 e3
-- arithmetic
eval (ADD (Number n1) (Number n2)) = Number $ n1 + n2
eval (ADD e1@(Number n1) e2) = ADD e1 (eval e2)
eval (ADD e1 e2) = ADD (eval e1) e2
eval (SUB (Number n1) (Number n2)) = Number $ n1 - n2
eval (SUB e1@(Number n1) e2) = SUB e1 (eval e2)
eval (SUB e1 e2) = SUB (eval e1) e2
-- equality
-- cases where both arguments are evaluated already
eval (EQ (Number n1) (Number n2)) = if n1 == n2 then T else F
eval (EQ T T) = T
eval (EQ F F) = T
eval (EQ T F) = F
eval (EQ F T) = F
-- left argument is evaluated, eval the right one
eval (EQ e1@(Number n1) e2) = EQ e1 (eval e2)
eval (EQ T e2) = EQ T (eval e2)
eval (EQ F e2) = EQ F (eval e2)
-- no argument is evaluated, eval the left one
eval (EQ e1 e2) = EQ (eval e1) e2
-- application
-- beta reduction
eval (App (Abs x p) q) = subst (\y -> if x == y then q else Var y) p
-- fixpoint combinator
eval (App Fix f) = App f (App Fix f)
-- reduce lhs
eval (App e1 e2) = App (eval e1) e2
-- products
eval (Fst (Pair t1 t2)) = t1
eval (Fst t) = Fst (eval t)
eval (Snd (Pair t1 t2)) = t2
eval (Snd t) = Snd (eval t)
-- sums and lists
eval (Case (Inl t) t1 t2) = App t1 t
eval (Case (Inr t) t1 t2) = App t2 t
eval (Case Nil t1 t2) = t1
eval (Case (Cons x xs) t1 t2) = App (App t2 x) xs
eval (Case t1 t2 t3) = Case (eval t1) t2 t3
-- Term is normalform
eval e = e
-- exhaustive evaluation
evalStar :: Term -> Term
evalStar e = if e == e' then e else evalStar e'
where e' = eval e

View file

@ -1,10 +1,5 @@
module Main where
{- |
Main entry point.
The `, run` script will invoke this function.
-}
main :: IO ()
main = do
print "Hello world"

42
src/Misc.hs Normal file
View file

@ -0,0 +1,42 @@
module Misc where
-- calculates free variables in a Term
freeVars :: Term -> [Name]
freeVars (Var x) = [x]
freeVars (ITE e1 e2 e3) = freeVars e1 ++ freeVars e2 ++ freeVars e3
freeVars (ADD e1 e2) = freeVars e1 ++ freeVars e2
freeVars (SUB e1 e2) = freeVars e1 ++ freeVars e2
freeVars (EQ e1 e2) = freeVars e1 ++ freeVars e2
freeVars (App e1 e2) = freeVars e1 ++ freeVars e2
freeVars (Abs x p) = filter (/= x) $ freeVars p
freeVars _ = []
-- infinite list of variable names (used for capture avoiding substitution)
vars :: [Name]
vars = ['v' : show n | n <- [1..]]
-- capture-avoiding substitution
subst :: (Name -> Term) -> Term -> Term
subst o (Var x) = o x
subst o (ITE e1 e2 e3) = ITE (subst o e1) (subst o e2) (subst o e3)
subst o (Case e1 e2 e3) = Case (subst o e1) (subst o e2) (subst o e3)
subst o (ADD e1 e2) = ADD (subst o e1) (subst o e2)
subst o (SUB e1 e2) = SUB (subst o e1) (subst o e2)
subst o (EQ e1 e2) = EQ (subst o e1) (subst o e2)
subst o (App e1 e2) = App (subst o e1) (subst o e2)
subst o (Cons e1 e2) = Cons (subst o e1) (subst o e2)
subst o (Pair e1 e2) = Pair (subst o e1) (subst o e2)
subst o (Fst e) = Fst (subst o e)
subst o (Snd e) = Snd (subst o e)
subst o (Inl e) = Inl (subst o e)
subst o (Inr e) = Inr (subst o e)
subst o e@(Abs x p) = Abs y (subst o' p)
where
y = if isFresh x then x else fromJust $ find isFresh vars
o' v
| v == x = Var y
| otherwise = o v
zs = map o $ freeVars e
isFresh :: Name -> Bool
isFresh e = not (any (elem e . freeVars) zs)
subst o e = e -- Terms without freeVars

45
src/Syntax.hs Normal file
View file

@ -0,0 +1,45 @@
module Syntax where
type Name = String
data Term
= T | F
| ITE Term Term Term
| Number Int
| ADD Term Term
| SUB Term Term
| EQ Term Term
| Fst Term
| Snd Term
| Inl Term
| Inr Term
| Case Term Term Term
| Nil
| Cons Term Term
| Pair Term Term
| Var Name
| App Term Term
| Abs Name Term
| Fix
deriving (Eq)
instance Show Term where
show T = "true"
show F = "false"
show (ITE t1 t2 t3) = "if (" ++ show t1 ++ ")\n then (" ++ show t2 ++ ")\n else (" ++ show t3 ++ ")"
show (Case t1 t2 t3) = "\n case (" ++ show t1 ++ ") of\n <0> => (" ++ show t2 ++ ");\n <1> => (" ++ show t3 ++ ")"
show (ADD t1 t2) = "(" ++ show t1 ++ ") + (" ++ show t2 ++ ")"
show (SUB t1 t2) = "(" ++ show t1 ++ ") - (" ++ show t2 ++ ")"
show (EQ t1 t2) = "(" ++ show t1 ++ ") == (" ++ show t2 ++ ")"
show (Number n) = show n
show (Fst t) = "fst " ++ show t
show (Snd t) = "snd " ++ show t
show (Inl t) = "inl " ++ show t
show (Inr t) = "inr " ++ show t
show Nil = "[]"
show (Cons t1 t2) = "(" ++ show t1 ++ ") : (" ++ show t2 ++ ")"
show (Pair t1 t2) = "(" ++ show t1 ++ ", " ++ show t2 ++ ")"
show (Var n) = n
show (App t1 t2) = "(" ++ show t1 ++ ") " ++ show t2
show Fix = "Y"
show (Abs x p) = "\\" ++ x ++ ". " ++ show p

3
src/Typecheck.hs Normal file
View file

@ -0,0 +1,3 @@
module Typecheck where
import Syntax