{-# OPTIONS -XRankNTypes #-}
import Value
import IntBool
import FunctionalEnvironment
compose f g = \x -> f(g x)
compose :: (b -> c) -> (a -> b) -> (a -> c)
square n = n * n
mulPi m = pi * m
areaR = compose mulPi square
areaD = compose areaR (\x -> x / 2)
testM1 = map negate [1, 3, -7, 0, 12]
-- returns [-1, -3, 7, 0, -12]
testM2 = [ negate n | n <- [1, 3, -7, 0, 12] ]
-- returns [-1, -3, 7, 0, -12]
type EnvL = [(String, Value)]
envL1 = [("x", IntV 3), ("y", IntV 4), ("size", IntV 10)]
envF1 "x" = Just (IntV 3)
envF1 "y" = Just (IntV 4)
envF1 "size" = Just (IntV 10)
envF1 _ = Nothing
x1 = lookup "x" envL1
x2 = envF1 "x"
bindL :: String -> Value -> EnvL -> EnvL
bindL var val env = (var, val) : env
envL2 = bindL "z" (IntV 5) envL1
-- [("z", IntV 5), ("x", IntV 3), ("y", IntV 4), ("size", IntV 10)]
envL3 = bindL "x" (IntV 9) envL1
-- [("x", IntV 9), ("x", IntV 3), ("y", IntV 4), ("size", IntV 10)]
-- version A
envF2 = bindF "z" (IntV 5) envF1
-- version B
envF2'1 = \testVar -> if testVar == "z"
then Just (IntV 5)
else envF1 testVar
-- version C
envF2'2 "z" = Just (IntV 5)
envF2'2 testVar = envF1 testVar
emptyEnvL :: EnvL
emptyEnvL = []
add a b = b + a
add'1 a = \b -> b + a
add'2 = \a -> \b -> b + a
add'3 = \a -> (\b -> b + a)
inc = add 1 -- \b. b + 1
dec = add (-1) -- \b. b + (-1)
eleven = inc 10
nine = dec 10
inc'1 = (\a -> (\b -> b + a)) 1
inc'2 = \b -> b + 1
inc'3 b = b + 1
testinc = inc 5 + inc 10 + dec 20 + dec 100
bindF'1 var val env testVar = if testVar == var
then Just val
else env testVar
true x y = x
false x y = y
type BooleanF = forall a. a -> a -> a
true :: BooleanF
false :: BooleanF
notF :: BooleanF -> BooleanF
notF b = b false true
orF :: BooleanF -> BooleanF -> BooleanF
orF a b = a true b
andF :: BooleanF -> BooleanF -> BooleanF
andF a b = a b false
testb1 = if not True then 1 else 2
testb2 = (notF true) 1 2
zero = \f -> \x -> x
one = \f -> \x -> f x
two = \f -> \x -> f (f x)
three = \f -> \x -> f (f (f x))
succ = \n -> (\f -> \x -> f (n f x))
type ChurchN = forall a. (a -> a) -> a -> a
church :: Integer -> ChurchN
church 0 = \f -> \x -> x
church n = \f -> \x -> f (church (n-1) f x)
unchurch :: ChurchN -> Integer
unchurch n = n (+1) 0
-- 5 == (unchurch (church 5)) -- this evaluates to True
plus :: ChurchN -> ChurchN -> ChurchN
plus n m = \f -> \x -> n f (m f x)
mul :: ChurchN -> ChurchN -> ChurchN
mul n m = \f -> n (m f)
main = do
print testM1
print testM2