# frosch03.de/posts/2013-12-11-HaskellExam

## My solution to a Haskell exam

Please keep in mind, that all the source is untested (as it would be in a real exam situation). If there are errors, I'm happy if you let me know.

### Exercise 1

Give the type of the following expressions: `Just`

, `Just Nothing`

,
`Just (Just True)`

, `Just Just`

, `Just (Just Just)`

I think, the easiest way to do this, is by starting to guess the type of the term in brackets. At least for the more complicated ones.

If the first type is clear, the rest should be straight forward.

Just :: a -> Maybe

Just Nothing :: Maybe (Maybe a) Just (Just True) :: Maybe (Maybe Bool) Just Just :: Maybe (a -> Maybe a) Just (Just Just) :: Maybe (Maybe (a -> Maybe a))

{% endhighlight %}

### Exercise 2

Write a function `catMaybes :: [Maybe a] -> [a]`

, that drop's all the
`Nothing`

values and only returns a list of the value within the `Just`

constructor.

Here you only have to parse the list, item by item. If you encounter a
`Just`

constructor, take the value inside and put it in the list. Than
go on with the rest-list.

catMaybes :: [Maybe a] -> [a] catMaybes [] = [] catMaybes ((Just x):ms) = x : (catMaybes ms) catMaybes (\_:ms) = catMaybes ms

### Exercise 3

Write a function `mapMaybe :: (a -> Maybe b) -> [a] -> [b]`

. The
supplied function produces `Maybe`

values. If it produces an
`Just b`

, then put the `b`

into the result list, otherwise do
nothing.

mapMaybe :: (a -> Maybe b) -> [a] -> [b] mapMaybe f (x:xs) | (Just \_) == f x = x :

| otherwise = mapMaybe f xs

{% endhighlight %}

### Exercise 4

Write a function `id :: a -> a`

, that returns arguments unchanged.

id :: a -> a id x = x

### Exercise 5

Write a function `null :: [a] -> Bool`

, that returns `True`

, if the list
is emtpy.

null :: [a] -> Bool null [] = False null otherwise = True

### Exercise 6

Write a function `map :: (a -> b) -> [a] -> [b]`

, that applies the
supplied function to all the arguments of the supplied list.

map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : (map f xs)

### Exercise 7

Write a function `concat :: [[a]] -> [a]`

, that tears down a list of
lists, to a simple list.

concat :: [[a]] -> [a] concat (x:xs) = x ++ (concat xs)

### Exercise 8

Write a function `length :: [a] -> Int`

, that returns the length of a
list

length :: [a] -> Int lenght [] = 0 length (\_:xs) = 1 + (length xs)

### Exercise 9

Write a function `any :: (a -> Bool) -> [a] -> Bool`

, that takes a
predicate function, and returns true, if in the list is any element that
supports that.

any :: (a -> Bool) -> [a] -> Bool any \_ [] = False any p (x:xs) | (p x) == True =

| otherwise = any p xs

{% endhighlight %}

### Exercise 10

Write a function `all :: (a -> Bool) -> [a] -> Bool`

, that takes a
predicate function, and returns true, only if all elements of the list
support the predicate function.

all :: (a -> Bool) -> [a] -> Bool all \_ [] = True all p (x:xs) | p x == True = all p

| otherwise = False

{% endhighlight %}

### Exercise 11

Write a function `concatMap :: (a -> [b]) -> [a] -> [b]`

, that supplies
a function to any element of a list, and concat's the results.

concatMap :: (a -> [b]) -> [a] -> [b] concatmap \_ [] = [] concatMap f (x:xs) = f x ++ (concatMap f xs)

### Exercise 12

Write a function `filter :: (a -> Bool) -> [a] -> [a]`

, that returns
only those elements of a list, that support the predicate.

filter :: (a -> Bool) -> [a] -> [a] filter \_ [] = [] filter p (x:xs) | p x == True = x :

| otherwise = filter p xs

{% endhighlight %}

### Exercise 13

How to use the `filter`

function, to get all the strings from a list of
string, that contain an 'a'?

stringsWithA :: [String] -> [String] stringsWithA = map $ filter (== 'a')

### Exercise 14

How to use the `filter`

function, to get a list of lists, where all
lists are longer than 10?

listLonger10 :: [[a]] -> [[a]] listLonger10 = map $ filter $ (>=10) . length

### Exercise 15

Give the type of the following expression: `filter (=`

'a')=,
`filter ((>10) . length)`

, `filter ((=`

'a') . head . fst . fst)=

filter (=='a') :: String -> String filter ((>10) . length) :: [[a]] -> [[a]] filter ((=='a') . head . fst . fst) :: (([String], a), b)

### Exercise 16

The following data type describes a tree. It's nodes hold lists of values, and it's leafs might hold values.

data Tree a = Br [a] (Tree a) (Tree a) | Lf (Maybe a)

- What is the
*kind*of`Tree`

? What is the type of`Br`

, and of`Lf`

?

> :kind Tree Tree :: * ->

> :type Br Br :: [a] -> Tree a -> Tree a -> Tree a > :type Lf Lf :: Maybe a -> Tree a

{% endhighlight %}

The kind is of *order* 2, because there is only one type needed to
produce a second one.

With the type constructor `Br`

, something of type `Tree a`

is produced.
In order to do so, a `[a]`

, and 2 `Tree a`

are needed.

- Write a function
`tree2lst`

, that writes all values of a tree into a list.

tree2lst :: Tree a -> [a] tree2lst (Br as lt rt) = (tree2lst lt) ++ as ++ (tree2lst rt) tree2lst (Lf (Just a)) = [a] tree2lst (Lf (Nothing)) = []

- Write an instance of
`Eq`

for`Tree a`

instance (Eq a) => Eq (Tree a) where (Br as lt rt) == (Br as' lt' rt') | as == as' = (lt == lt') &&

| otherwise = False (Lf a) == (Lf a') | a == a' = True | otherwise = False

{% endhighlight %}

These trees are equal, if there are two branches, with equal lists, and also if both sub-trees are equal, too.

They are also equal, if they are two leafs with equal value, and also if both have no value.

Otherwise, the trees are unequal.

- Write an instance of
`Functor`

for`Tree a`

instance Functor Tree where fmap f (Br as lt rt) =

fmap f (Lf (Just a)) = (Lf (Just (f a))) fmap _ (Lf Nothing) = (Lf Nothing)

{% endhighlight %}

Ok, `Functor`

want's you, to write an `fmap`

function. That function
awaits a function, which is executed on every value inside the tree.

The function is mapped over the list of a branch, and is propagated to the sub-trees via fmap.

The propagation stops at the leafs.

- Write a fold function
`foldTree`

for the`Tree a`

type

foldTree :: (b -> a -> b) -> b -> (Tree a) -> b foldTree f n (Br as lt rt) =

foldTree f n (Lf (Just a)) = f n a foldTree _ n _ = n

{% endhighlight %}

To fold something means, to tear a structure down. Therefore a function
is used, that can consume a value of the tree at a time. That value,
together with the result *so far*, is computed into the next result *so
far*.

For the first calculation, a initial value is also needed.

That initial value is used, in combination with the left sub-tree, to
calculate the result *so far* from the left tree. That result is used,
together with the right tree, to calculate the next result *so far*.

At last, that result is supplied to a fold function for lists, to calculate a final result.

With the help of

`foldTree`

, write a`sumTree`

function, that sumsall up all values inside the tree.

foldTree (+) 0

If `Foldtree`

is supplied with the addition function, and 0, the initial
calculation would be a value of the tree plus 0. That is then added to
the next value of the tree, until all values are consumed. The last
result is the final result.

### 17 With the data type

data Either a b = Left a | Right b

- Write an instance of
`Functor`

for`Either`

instance Functor (Either a) where fmap \_ (Left a) = Left

fmap f (Right b) = (Right (f b))

{% endhighlight %}

Again, `Functor`

needs a definition of the `fmap`

function. `fmap`

takes
a function, that transforms an inner value, and a capsuled value. It
executes the function on the inner value of the capsule, and puts the
result back into the capsule.

Keep in mind, that you only have to take action on the `Right`

side,
because the `Left`

side is constrained to `a`

.

- Write an instance of
`Monad`

for`Either`

instance Monad (Either a) where (>>=) (Right a) f =

(>>=) (Left x) _ = (Left x) return x = (Right x)

{% endhighlight %}

For `Monad`

a combination operator and a capsule operator must be
defined. Again, only the `Right`

side must be calculated, the `Left`

side is constrained.

The capsuling returns everything supplied also only to the `Right`

constructor.

### 18 Write monadic versions for list functions

- Write a monadic version
`filterM`

filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a] filterM f [] = return [] filterM f (a:as) = f a >>= (\n -> let x = filterM f as in if n == True then x >>= (\x'-> return (a:x')) else x)

The function returns just a monadic version of the empty list, if the empty list is supplied.

For all other lists, the predicate function is executed on the first
element of the list. The result is passed into a new function. There `a`

is added to the result list, only if `f a`

resulted in true.

- Write a monadic version
`mapM`

mapM :: (Monad m) => (a -> m b) -> [a] -> m [b] mapM f [] = return [] mapM f (a:as) = f a >>= (\n -> let x = mapM f as in x >>= (\x'-> return (n:x')))\\

The scheme is the same here as in `filterM`

. The supplied monadic
function is applied to the first element of the list. The calculated
value is then bound, via a lambda expression, to the identifier `n`

.
`mapM`

is executed on the rest list. The value `n`

is than appended to
the result of the inner `mapM`

.

- Write a monadic version
`zipWithM`

zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c] zipWithM \_ [] \_ = return [] zipWithM [] \_ \_ = return [] zipWithM f (a:as) (b:bs) = f a b >>= (\n -> let x = zipWithM f as bs in x >>= (\x'-> return (n:x')))

Again, the schema is here exactly the same, as in the previous two. Calculate the first value, and bind it to the rest values.

- Write a function, that applies a function embedded in a monad, to values inside that monad.

ap :: (Monad m) => m (a -> b) -> m a -> m b ap f x = f >>= (\f'-> (x >>= (\x' -> return (f' x'))))

Here, obviously `f`

must be executed on `x`

. Therefore both are catched
within the prime variants and are then applied.

The result is then packed back inside the monad.

### 19 Write text file processing functions

Assume, that there is a `test.txt`

file in the actual directory.

- Write a program to count the lines within
`test.txt`

lineNums :: IO Int lineNums = do file <- readFile "/tmp/test.txt" return $ length . lines $ file

The first thing would always be, to read the file into `file`

. Then the
`lines`

function splits the `file`

string into it's lines. After that,
the `length`

is the line count.

- Write a function, that counts the number of words with more than 2 letters.

countWordsLonger2 :: IO Int countWordsLonger2 = do file <- readFile "/tmp/test.txt" ws <- return $ words file return $ length $ filter ((>2) . length) ws

The file is read. Then the content is split up into words. With `filter`

only the words, that have a length that is greater 2 `(>2) . length`

,
are returned. The length of that list is the number of such words.

- Write a function that prints the lines that contain an 'a'

printLinesWithA :: IO () printLinesWithA = do file <- readFile "/tmp/test.txt" ls <- return $ lines file ls' <- return $ filter (foldl fn False) ls putStrLn $ unlines ls' return () where fn \_ 'a' = True fn r \_ = r

Here the file is read and split up into it's lines. With filter, some
lines are filtered out. Which, is determined by a fold, that returns
`False`

if there is no 'a' within the line, and `True`

otherwise. These
lines are then printed with `putStrLn`

.

- Write a function, that returns the longest line, that does not contain an 'a'.

lineContains :: Char -> String -> Bool lineContains c = foldl (\r n -> if n == c then True else r) False

tLongestLineWithoutA :: IO () printLongestLineWithoutA = do file <- readFile "/tmp/test.txt" ls <- return $ lines file ls' <- return $ filter (not . lineContains 'a') ls longest <- return $ foldl (\r n -> if length n > length r then n else r) "" ls' putStrLn longest return ()

First of all, the `fold fn`

function from 19.3 is here put into a helper
function, called `lineContains`

. That function takes a character and a
string and returns a boolean value, that indecates, if the char is
within that line.

Then the actual function reads the file, and splits it into lines. These lines are then filtered for lines that do not contain an 'a'.

That result contains all possible lines and another fold is used to break it down to only one line, the longest line.

- Write a function, that returns the number of words of the line with the most words.

longestLineWordCount :: IO Int longestLineWordCount = do file <- readFile "/tmp/test.txt" ls <- return $ lines file putStrLn $ return $ foldl fn 0 (words ls) where fn r n | n > r = n | otherwise = r

Again, a simple fold is used, to return the number of words of the longest line. The fold compares the actual highest number of words, with that of the next line. Only if the next line contains more words, than the actual line, the actual number is taken.

- Write a function, that returns the longest word

longestWord :: IO () longestWord = do file <- readFile "/tmp/test.txt" ws <- return $ words file putStrLn $ return $ foldl fn "" ws return () where fn r n | (length n) > (length r) = n | otherwise = r

Here is the file split into it's words. Then with a fold, only the longest word is passed.