module HW6 where import Prelude hiding (print,and,or,not,pred,succ,fst,snd,either,length,sum,product) import DeBruijn -- -- * Part 1: Nameless lambda calculus -- -- | λx. (λx.x) x -- -- >>> eval ex1 -- Abs (Ref 0) -- ex1 :: Exp ex1 = undefined -- | (λxy.xz) z z -- -- >>> eval ex2 -- App (Ref 0) (Ref 0) -- ex2 :: Exp ex2 = undefined -- | λy. (λxy.yx) y z -- -- >>> eval ex3 -- Abs (App (Ref 1) (Ref 0)) -- ex3 :: Exp ex3 = undefined -- | Is the given nameless lambda calculus term a closed expression? That is, -- does it contain no free variables? -- -- >>> closed (Ref 0) -- False -- -- >>> closed (Abs (Ref 0)) -- True -- -- >>> closed (Abs (App (Ref 0) (Ref 1))) -- False -- -- >>> closed (Abs (App (Abs (App (Ref 0) (Ref 1))) (Ref 0))) -- True -- closed :: Exp -> Bool closed = undefined -- -- * Part 2: Church pair update functions -- -- | Write a lambda calculus function that replaces the first element in a -- Church-encoded pair. The first argument to the function is the new -- first element, the second argument is the original pair. -- -- >>> :{ -- eval (app2 pair true (num 3)) == -- eval (app2 setFst true (app2 pair (num 2) (num 3))) -- :} -- True -- setFst :: Exp setFst = undefined -- | Write a lambda calculus function that replaces the second element in a -- Church-encoded pair. The first argument to the function is the new -- second element, the second argument is the original pair. -- -- >>> :{ -- eval (app2 pair (num 2) true) == -- eval (app2 setSnd true (app2 pair (num 2) (num 3))) -- :} -- True -- setSnd :: Exp setSnd = undefined -- -- * Part 3: Church encoding a Haskell program -- -- | Pretend Haskell's Int is restricted to Nats. type Nat = Int -- | A simple data for representing shapes. data Shape = Circle Nat | Rectangle Nat Nat deriving (Eq,Show) -- | A smart constructor for building squares. square :: Nat -> Shape square l = Rectangle l l -- | Compute the area of a shape using a rough approximation of pi. area :: Shape -> Nat area (Circle r) = 3 * r * r area (Rectangle l w) = l * w -- | Compute the perimeter of a shape using a rough approximation of pi. perimeter :: Shape -> Nat perimeter (Circle r) = 2 * 3 * r perimeter (Rectangle l w) = 2 * l + 2 * w -- | Encode the circle constructor as a lambda calculus term. The term -- should be a function that takes a Church-encoded natural number as input -- and produces a Church-encoded shape as output. circleExp :: Exp circleExp = undefined -- | Encode the rectangle constructor as a lambda calculus term. The term -- should be a function that takes two Church-encoded natural numbers as -- input and produces a Church-encoded shape as output. rectangleExp :: Exp rectangleExp = undefined -- | Convert a shape into a lambda calculus term. This function helps to -- illustrate how your encodings of the constructors should work. encodeShape :: Shape -> Exp encodeShape (Circle r) = App circleExp (num r) encodeShape (Rectangle l w) = app2 rectangleExp (num l) (num w) -- | Encode the square function as a lambda calculus term. squareExp :: Exp squareExp = undefined -- | Encode the area function as a lambda calculus term. areaExp :: Exp areaExp = undefined -- | Encode the perimeter function as a lambda calculus term. perimeterExp :: Exp perimeterExp = undefined -- | Some tests of your lambda calculus encodings. -- -- >>> :{ -- checkEval (area (Circle 3)) -- (App areaExp (App circleExp (num 3))) -- :} -- True -- -- >>> :{ -- checkEval (area (Rectangle 3 5)) -- (App areaExp (app2 rectangleExp (num 3) (num 5))) -- :} -- True -- -- >>> :{ -- checkEval (area (square 4)) -- (App areaExp (App squareExp (num 4))) -- :} -- True -- -- >>> :{ -- checkEval (perimeter (Circle 3)) -- (App perimeterExp (App circleExp (num 3))) -- :} -- True -- -- >>> :{ -- checkEval (perimeter (Rectangle 3 5)) -- (App perimeterExp (app2 rectangleExp (num 3) (num 5))) -- :} -- True -- -- >>> :{ -- checkEval (perimeter (square 4)) -- (App perimeterExp (App squareExp (num 4))) -- :} -- True -- checkEval :: Nat -> Exp -> Bool checkEval n e = num n == eval e