Ex 10 Solutions

Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Prof. Dr.

Ralf Hinze TU Kaiserslautern


M.Sc. Sebastian Schloßer
Fachbereich Informatik
AG Programmiersprachen

Functional Programming: Exercise 10


Sheet published: Friday, July 8th
Exercise session: Thursday, July 14th, 12:00

Exercise 10.1. Show that this definition of the Reader Monad fulfils the Monad laws:

newtype Reader env a = Reader {runReader :: env → a }


instance Monad (Reader env ) where
return x = Reader (\ → x )
>= g = Reader (\x → runReader (g (f x )) x )
(Reader f ) >

For the proof, we leave out the Reader constructor and runReader accessor function:

return x = \ → x
f >>= g = \x → (g (f x )) x

f >>= return return a >>= f


= { def. >
>= } = { def. >>= }
\x → return (f x ) x \x → f (return a x ) x
= { def. return } = { def. return }
\x → f x \x → f a x
= { extensionality } = { extensionality }
f f a

(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:

type Pair a = (a, a)


data Perfect a = Zero a
| Succ (Perfect (Pair a))

a) Write a function

height :: Perfect a → Integer

that calculates the height of the tree.

height (Zero ) = 1
height (Succ t) = 1 + height t

b) Write a function

toList :: Perfect a → [a ]

that transforms the tree to a list.

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.

instance Functor Perfect where


fmap f (Zero x ) = Zero (f x )
fmap f (Succ t) = Succ (fmap (\(x , y) → (f x , f y)) t)

Base case: Zero x


Need to show: fmap id (Zero x ) = Zero x

fmap id (Zero x )
= { def. fmap }
Zero (id x )
= { def. id }
Zero x

Induction step: Succ t


Induction Hypothesis: fmap id t = t
Need to show: fmap id (Succ t) = Succ t

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

mirror :: Perfect a → Perfect a

that mirrors the tree such that toList ◦ mirror = reverse ◦ toList.

mirror (Zero x ) = Zero x


mirror (Succ t) = Succ (fmap (\(x , y) → (y, x )) (mirror t))

e) Write a function

fromList :: [a ] → Maybe (Perfect a)

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:

newtype ChurchList a = CL (∀b.(a → b → b) → b → b)

The type ChurchList a is isomorphic to the type [a ]. The ChurchList a representation


takes a binary operation (a → b → b) and an initial value (b). It applies the operation to
all elements from the list plus the initial value in a right-associative way. Think of it as
an instance of the foldr function where the list has already been provided.

a) Provide representations for both list constructors:

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 )

b) We also need a way to consume lists of type ChurchList a. Implement a function

foldr :: (a → b → b) → b → ChurchList a → b

that behaves like foldr for normal Haskell lists of type [a ].

foldr f y (CL xs) = xs f y

c) Provide a Functor instance for ChurchList, i.e. implement a function

fmap :: (a → b) → ChurchList a → ChurchList b

We could just use foldr :

fmap f xs = foldr (\x ys → cons (f x ) ys) nil xs

We can simplify it to a direct implementation:

fmap f (CL xs) = CL $ \g → xs (g ◦ f )

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.

fromList = foldr cons nil


toList = foldr (:) [ ]

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

safeHead :: ChurchList a → Maybe a


safeTail :: ChurchList a → Maybe (ChurchList a)
append :: ChurchList a → ChurchList a → ChurchList a

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.

safeHead (CL xs) = xs (\a → Just a) Nothing


safeTail (CL xs) = snd (xs (\x ∼(r , ) → (cons x r , Just r )) (nil , Nothing))
append (CL xs) (CL ys) = CL $ \f r → xs f (ys f r )

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:

iiii length $ foldr (+


+) [] (take 10000 (repeat [1]))
iiii length $ foldl (+
+) [] (take 10000 (repeat [1]))
iiii length $ foldr append nil (take 10000 (repeat (cons 1 nil )))
iiii length $ foldl append nil (take 10000 (repeat (cons 1 nil )))

a
https://wiki.haskell.org/Lazy_pattern_match

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy