Ex 10 Solutions
Ex 10 Solutions
Ex 10 Solutions
Exercise 10.1. Show that this definition of the Reader Monad fulfils the Monad laws:
For the proof, we leave out the Reader constructor and runReader accessor function:
return x = \ → x
f >>= g = \x → (g (f x )) x
(f >>= g) >
>= h
= { def. inner >
>= }
(\x → (g (f x )) x ) >
>= h
= { def. >
>= }
\x → (h (g (f x )) x ) x
= { extensionality, read the remaining proof bottom-up }
\x → (\x → (h (g (f x )) x ) x ) x
= { def. >
>= }
\x → (g (f x ) >
>= h) x
= { def. outer >
>= }
f >>= \a → (g a >
>= h)
1
Exercise 10.2 (Skeleton: Perfect.hs). Consider the following data type for trees con-
taining exactly 2n (n ∈ N) elements:
a) Write a function
height (Zero ) = 1
height (Succ t) = 1 + height t
b) Write a function
toList :: Perfect a → [a ]
toList (Zero x ) = [x ]
toList (Succ t) = [z | (x , y) ← toList t, z ← [x , y ]]
c) Provide a Functor instance for Perfect and prove that it satisfies the first functor law.
fmap id (Zero x )
= { def. fmap }
Zero (id x )
= { def. id }
Zero x
2
fmap id (Succ t)
= { def. fmap }
Succ (fmap (\(x , y) → (id x , id y)) t)
= { def. id }
Succ (fmap (\(x , y) → (x , y)) t)
= { def. id (specialized to pair type) }
Succ (fmap id t)
= { induction hypothesis }
Succ t
d) Write a function
that mirrors the tree such that toList ◦ mirror = reverse ◦ toList.
e) Write a function
that transforms the list into a perfect tree. This is possible only if the list contains
exactly 2n (n ∈ N) elements.
fromList [ ] = Nothing
fromList [x ] = Just (Zero x )
fromList xs = fmap Succ (pass xs >>= fromList) where
pass :: [a ] → Maybe [(a, a)]
pass [ ] = Just [ ]
pass [ ] = Nothing
pass (x : y : zs) = fmap ((x , y):) (pass zs)
3
Exercise 10.3 (Skeleton: Lists.hs). Lists can be represented as functions:
nil :: ChurchList a
cons :: a → ChurchList a → ChurchList a
nil = CL $ \ r → r
cons x (CL xs) = CL $ \f r → f x (xs f r )
foldr :: (a → b → b) → b → ChurchList a → b
4
d) Implement functions
fromList :: [a ] → ChurchList a
toList :: ChurchList a → [a ]
that convert normal Haskell lists to our ChurchList a representation and vice verca.
Instead of using cons and nil , we can also provide a direct implementation:
fromList xs = CL $ \f r → foldr f r xs
e) Implement functions
that correspond to head , tail and ++ for normal lists of type [a ]. Note that safeHead
and safeTail have a Maybe return type to handle empty input lists.
The tilde (∼) in safeTail makes the pattern match lazya . The lambda expression
is equivalent to \x pair → let (r , ) = pair in (cons x r , Just r ). Lazy pattern
matching is required here to ensure that safeTail always is productive; think of e.g.
safeTail (fromList [1 . .]) which otherwise hangs without producing output.
safeHead and append are constant time operations, safeTail needs linear time. For
normal Haskell lists, head and tail are constant time, whereas ++ needs time linear
in the length of the first parameter.
In the interpreter, type :set +s to enable statistics and then compare:
a
https://wiki.haskell.org/Lazy_pattern_match