Exercises part 1
In these exercises you are going to implement several recursive functions. Make sure to use tail recursion whenever possible and quickly verify the correct behavior of all functions at the REPL.
-
Implement functions
anyList
andallList
, which returnTrue
if any element (or all elements in case ofallList
) in a list fulfills the given predicate:anyList : (a -> Bool) -> List a -> Bool allList : (a -> Bool) -> List a -> Bool
-
Implement function
findList
, which returns the first value (if any) fulfilling the given predicate:findList : (a -> Bool) -> List a -> Maybe a
-
Implement function
collectList
, which returns the first value (if any), for which the given function returns aJust
:collectList : (a -> Maybe b) -> List a -> Maybe b
Implement
lookupList
in terms ofcollectList
:lookupList : Eq a => a -> List (a,b) -> Maybe b
-
For functions like
map
orfilter
, which must loop over a list without affecting the order of elements, it is harder to write a tail recursive implementation. The safest way to do so is by using aSnocList
(a reverse kind of list that's built from head to tail instead of from tail to head) to accumulate intermediate results. Its two constructors areLin
and(:<)
(called the snoc operator). ModuleData.SnocList
exports two tail recursive operators called fish and chips ((<><)
and(<>>)
) for going fromSnocList
toList
and vice versa. Have a look at the types of all new data constructors and operators before continuing with the exercise.Implement a tail recursive version of
map
forList
by using aSnocList
to reassemble the mapped list. Use then the chips operator with aNil
argument to in the end convert theSnocList
back to aList
.mapTR : (a -> b) -> List a -> List b
-
Implement a tail recursive version of
filter
, which only keeps those values in a list, which fulfill the given predicate. Use the same technique as described in exercise 4.filterTR : (a -> Bool) -> List a -> List a
-
Implement a tail recursive version of
mapMaybe
, which only keeps those values in a list, for which the given function argument returns aJust
:mapMaybeTR : (a -> Maybe b) -> List a -> List b
Implement
catMaybesTR
in terms ofmapMaybeTR
:catMaybesTR : List (Maybe a) -> List a
-
Implement a tail recursive version of list concatenation:
concatTR : List a -> List a -> List a
-
Implement tail recursive versions of bind and
join
forList
:bindTR : List a -> (a -> List b) -> List b joinTR : List (List a) -> List a