Written by Isaiah Oloyede
on
on
Chapter 4: Basic Datatypes
This note captures my solutions to exercises in Chapter 4: Basic Datatypes of the book Haskell programming from first principles
Exercises: Mood swing
- The type constructor is
Mood
. - If the function requires a
Mood
value, we can only useBlah
orWoot
. - What is wrong with
changeMood :: Mood -> Woot
is thatWoot
is not a type constructor. It is a data constructor. A data constructor cannot appear in the type signature, it can only appear at the term level. - Mood should not appear at the term level since it is a type constructor. Fixed function is shown below.
module ChangeMood where
data Mood = Blah | Woot deriving Show
changeMood :: Mood -> Mood
changeMood Blah = Woot
changeMood _ = Blah
Exercises: Find the mistakes
not True && true
should benot True && True
not (x = 6)
should benot (x == 6)
. This will not compile because x is not defined.(1 * 2) > 5
. This works without any fix.[Merry] > [Happy]
should be["Merry"] > ["Happy"]
.[1, 2, 3] ++ "look at me!"
should be['1','2','3'] ++ "look at me!"
.
Chapter exercises
awesome = ["Papuchon", "curry", ":)"]
alsoAwesome = ["Quake", "The Simons"]
allAwesome = [awesome, alsoAwesome]
Question 1
length
has a type signature [a] -> Int
. It takes a list of any type. It evaluates to a type of Int
.
Question 2
length [1, 2, 3, 4, 5]
gives5
.length [(1, 2), (2, 3), (3, 4)]
gives3
. This is a list of tuples.length allAwesome
gives 2.allAwesome
is a list of two values:awesome
andalsoAwesome
.length (concat allAwesome)
gives5
.concat
flattensallAwesome
and produces a list of 5 strings.
Question 3
6 / 3
works. This produces 2.0
. 6 / length [1, 2, 3]
returns an error because length
returns an Int
datatype whereas the operator (/)
belongs to a Fractional
typeclass which has no instance for the Int
datatype. Int
belongs to the Integral
typeclass instead.
Question 4
We can use div
function. Alternatively, we can use fromIntegral
to coerce the Integral
typeclass to Num
typeclass. fromIntegral
has a type (Integral a, Num b) => a -> b
.
-- #4
-- Using a different operator
ghci> 6 `div` length [1, 2, 3]
2
-- Alternatively
ghci> 6 / fromIntegral (length [1, 2, 3])
2.0
Question 5
The type of the expression 2 + 3 == 5
is Bool
. The expected result is True
.
Question 6
- The type of
x
inx = 5
isNum a => a
. The expected result is5
. - The type of
x + 3 == 5
isBool
. The expected result isFalse
ifx = 5
.
Question 7
length allAwesome == 2
givesTrue
. This works because we are comparing two values of the same datatypeInt
.length [1, 'a', 3, 'b']
does not work because a list cannot contain values of different datatypes.length allAwesome + length awesome
gives5
. This works because we are adding values of the same datatypeInt
.(8 == 8) && ('b' < 'a')
givesFalse
. This works because we are performing a boolean And operation on two values of theBool
datatype.(8 == 8)
isTrue
and('b' < 'a')
isFalse
, thereforeTrue
andFalse
givesFalse
.(8 == 8) && 9
does not work because we are trying to compareBool
with a numeric datatype.
Question 8
module IsPalindrome where
isPalindrome :: (Eq a) => [a] -> Bool
isPalindrome x = x == reverse x
Question 9
module MyAbs where
myAbs :: Integer -> Integer
myAbs x = if x >= 0 then x else -x
Question 10
f :: (a, b) -> (c, d) -> ((b, d), (a, c))
f x y = (,) (snd x, snd y) (fst x, fst y)
Correcting syntax
module CorrectingSyntax where
-- #1
x :: Int -> Int -> Int
x = (+)
f :: Foldable t => t a -> Int
f xs = w `x` 1 where
w = length xs
-- #2
f' :: p -> p
f' x = x
-- #3
f'' :: (a, b) -> a
f'' (a, b) = a
Match the function names to their types
- The type of
show
isShow a => a -> String
(option c). - The type of
(==)
isEq a => a -> a -> Bool
(option b). - The type of
fst
is(a, b) -> a
(option a). - The type of
(+)
is(+) :: Num a => a -> a -> a
(option d).