id := (λa. a)
self apply := (λa. a a)
0 := (λf.a. a)
1 := (λf.a. f a)
2 := (λf.a. f (f a))
...
true := (λa.b. a)
false := (λa.b. b)
pair := (λa.b.f. f (x y))
first := (λp. p (λa.b. a)) -- pair a b true
second := (λp. p (λa.b. b)) -- pair a b false
... etc
Could we use recursion?
The rules mean we can't use named recursion.
What about self application?
More than Mohan's favorite news site
fix := λf(.x. f (x x) (λx. f (x x)))
fix :: (a -> a) -> a
fix f = let
dupe fx = fx (dupe fx)
in fx f
Fixed Points
An input x where f(x)=x. Not all functions have them, some may have more than one.
-- All n <= 1 are fixed points
factorial :: Int -> Int
factorial = fix (\rec n -> if n <= 1 then 1 else n * rec (n-1))
Defining Addition on Church numerals
fix (λf. (x,n). ->
if isZero x
then n
else f (pred x, succ n)
)
class LambdaCalc repr where
zero :: repr Int
pred :: repr Int -> repr Int
succ :: repr Int -> repr Int
lam :: forall a b. (repr a -> repr b) -> repr (a -> b)
app :: forall a b. repr (a -> b) -> repr a -> repr b
fix :: forall a. (repr a -> repr a) -> repr a
newtype Eval a = Eval a
unwrap :: forall a. Eval a -> a
unwrap (Eval a) = a
instance lambdaEval :: LambdaCalc Eval where
zero = Eval 0
pred (Eval 0) = Eval 0
pred (Eval n) = Eval (n - 1)
succ (Eval n) = Eval (n + 1)
lam f = Eval $ unwrap <<< f <<< Eval
app (Eval f) = \(Eval a) -> Eval (f a)
fix f = Eval $ dupe (unwrap <<< f <<< Eval)
where dupe fx = fx (dupe fx)
eval :: forall a. Show a => Eval a -> String
eval = show <<< unwrap