Real World Haskell – Exercises Chapter 3

My answers to the exercises of chapter 3.

Page 60:

1. Write the converse of fromList for the List type: a function that takes a List a and generates a [a].

toList :: List a -> [a]
toList (Cons x y) = x : toList y
toList Nil        = []

2. Define a tree type that has only one constructor, like our Java example. Instead of the Empty constructor, use the Maybe type to refer to a node’s children.

data Tree a = Node a (Maybe (Tree a)) (Maybe (Tree a))
              deriving (Show)

Page 69:

1. Write a function that computes the number of elements in a list. To test it, ensure that it gives the same answers as the standard length function.

myLength []     = 0
myLength (x:xs) = 1 + myLength xs

2. Add a type signature for your function to your source file. To test it, load the source file into ghci again.

myLength :: [a] -> Integer
myLength []     = 0
myLength (x:xs) = 1 + myLength xs

3. Write a function that computes the mean of a list, i.e. the sum of all elements in the list divided by its length. (You may need to use the fromIntegral function to convert the length of the list from an integer into a floating point number.)

mean xs = sum xs / fromIntegral (length xs)

4. Turn a list into a palindrome, i.e. it should read the same both backwards and forwards. For example, given the list [1,2,3], your function should return [1,2,3,3,2,1].

palindrome xs = xs ++ reverse xs

5. Write a function that determines whether its input list is a palindrome.

isPalindrome xs = xs == reverse xs

6. Create a function that sorts a list of lists based on the length of each sublist. (You may want to look at the sortBy function from the Data.List module.)

sortByLength xss = sortBy cmpLength xss
  where
    cmpLength =  xs ys -> compare (length xs) (length ys)

Or, less bulky, using the on function from the Data.Function module.

sortByLength' = sortBy (compare `on` length)

7. Define a function that joins a list of lists together using a separator value.

intersperse :: a -> [[a]] -> [a]
intersperse _ []       = []
intersperse _ (xs:[])  = xs
intersperse s (xs:xss) = xs ++ [s] ++ (intersperse s xss)

8. Using the binary tree type that we defined earlier in this chapter, write a function that will determine the height of the tree. The height is the largest number of hops from the root to an Empty. For example, the tree Empty has height zero; Node "x" Empty Empty has height one; Node "x" Empty (Node "y" Empty Empty) has height two; and so on.

height :: Tree a -> Integer
height (Node _ x y) = 1 + max (height x) (height y)
height Empty        = 0

9. Consider three two-dimensional points a, b, and c. If we look at the angle formed by the line segment from a to b and the line segment from b to c, it either turns left, turns right, or forms a straight line. Define a Direction data type that lets you represent these possibilities.

data Direction = LeftTurn
               | RightTurn
               | Straight
                 deriving (Show)

Real World Haskell – Exercises Chapter 2

My answers to the exercises of the second chapter.

Page 25:

1. What are the types of the following expressions?

False :: Bool
(["foo", "bar"], 'a') :: ([String], Char)
[(True, []), (False, [['a']])] :: [(Bool,[[Char]])]

Page 39:

1. Haskell provides a standard function, last :: [a] -> a, that returns the last element of a list. From reading the type alone, what are the possible valid behaviors (omitting crashes and infinite loops) that this function could have?

From the type alone there is no way to find out what the real type is, neither is there a way to manipulate a value of that type, thus the “only” thing the code can do is return an element of the list.

What are a few things that this function clearly cannot do?

  • Return the size of the list.
  • Reverse the list.

2. Write a function, lastButOne, that returns the element before the last.

lastButOne = head . tail . reverse

Load your lastButOne function into ghci and try it out on lists of different lengths. What happens when you pass it a list that’s too short?

Prelude> lastButOne "a"
*** Exception: Prelude.head: empty list

Real World Haskell – Exercises Chapter 1

Here are my answers to the exercises of chapter 1.

1. Enter the following expressions into ghci What are their types?

Prelude> 5 + 8
5 + 8
13
it :: Integer
Prelude> 3 * 5 + 8
3 * 5 + 8
23
it :: Integer
Prelude> 2 + 4
2 + 4
6
it :: Integer
Prelude> (+) 2 4
(+) 2 4
6
it :: Integer
Prelude> sqrt 16
sqrt 16
4.0
it :: Double
Prelude> succ 6
succ 6
7
it :: Integer
Prelude> succ 7
succ 7
8
it :: Integer
Prelude> pred 9
pred 9
8
it :: Integer
Prelude> pred 8
pred 8
7
it :: Integer
Prelude> sin (pi / 2)
sin (pi / 2)
1.0
it :: Double
Prelude> truncate pi
truncate pi
3
it :: Integer
Prelude> round 3.5
round 3.5
4
it :: Integer
Prelude> round 3.4
round 3.4
3
it :: Integer
Prelude> floor 3.7
floor 3.7
3
it :: Integer
Prelude> ceiling 3.3
ceiling 3.3
4
it :: Integer

2. From ghci, type :? to print some help. Define a variable and then type :show bindings. What do you see?

Prelude> let x = 1
let x = 1
Prelude> :show bindings
:show bindings
it :: Integer = 4
x :: Integer = _
Prelude> x
x
1
Prelude> :show bindings
:show bindings
it :: Integer = 4
x :: Integer = 1

3. The words function counts the number of words in a string. Modify the WC.hs example in order to count the number of words in a file.

main = interact wordCount
  where wordCount input = show (length (words input)) ++ "n"

4. Modify the WC.hs example again, in order to print the number of characters in a file.

main = interact wordCount
  where wordCount input = show (length input) ++ "n"