-- Square and Increment functions
let square = \x -> x*x
let increment = \x -> x+1
---- Combinators
-- Identity combinator
let i = \x -> x
i 5
i square 5
let sq = i square
sq 5
-- Application combinator
let app = \f -> \x -> f x
app square 7
let sq = app square
sq 7
-- Sequencing combinator, z should not appear free in e2
let seq e1 e2 = (\z -> e2) e1
seq 3 4
-- Currying is first class in Haskell
let plus x y = x+y
-- equivalent to
let plus = \x -> \y -> x+y
plus 4 5
let plus2 = plus 2
plus2 3
-- Function composition combinator
-- the following four are equivalent forms:
let compose f g x = f (g x)
let compose f g = \x -> f (g x)
let compose f = \g -> \x -> f (g x)
let compose = \f -> \g -> \x -> f (g x)
compose square increment 5
-- Currying compose (applying it to less arguments):
let incrementC = compose increment
let squaredPlusOne = incrementC square
-- same as
let squaredPlusOne = compose increment square
squaredPlusOne 4
let incrementTwice = incrementC increment
incrementTwice 5
-- Using curried compose increment with an anonymous function:
incrementC (\x -> x+2) 4