You are on page 1of 5

Hutton Book Notes

Chapter 1
[pg 10]The order in which functions are applied does not affect the value of the
result but may affect the number of operations and whether the calculation
process terminates
[pg 10 - 11]
Functional programming is a style of programming which emphasises the applicatio
of functions to arguments.
Specifically contrasted against the imperative style where the emphasis is on
changing stored values via assignment.
[pg 12]
Some imperative languages have a function construct, but often do not allow
first class functions (functions can be passed as arguments, returned as results
and stored in datastructures) and do not encourage generators etc.
Chapter 3 Types
Types are collections of values.
e.g: Type Bool has two values, True and False
Basic Types = Bool, Char, String, Int, Integer, Float
'Compound Types' = Lists, Tuples, Functions
Curried Functions : essentially -> associates to the right so
f :: a -> a -> a is really f :: a -> ( a -> a)
the function application operator (the empty space) associates to the left so
f 1 2 is really (f 1) 2
Currying enables partial application of functions.
KEY: Unless tupling is explicitly required all functions in Haskell are defined
as curried functions
A type that has one or more type variables is called a polymorphic type
(note: compound types include list, tuple and function types, so we can have
polymorphic tuples, lists, functions)
e.g: :t length gives length :: [a] -> Int -- before Foldable refactoring etc
so the (function) type of length is polymorphic
An expression with a polymorphic type is also polymorphic
thus length is a polymorphic function. It accepts lists of values with any type
Overloaded types are types with *constraints* on the type variables.
thus :t (+) gives (+) :: (Num a) => a -> a -> a
this says that + works on those types which are instances of the the (type)class
Num. All types in this class have numeric values.
This is interesting since 'normal' programmer talk would consider 'length' to be
an overloaded function too.

A typeclass is a collection of types (just as a type is a collection of values)

that support (== ??) an overloaded functions called methods.
iow, the types that are members of a typeclass can all be substituted for
the type variables in the type declaration of the classes methods.
Many built in typeclasses.
Eq class contains types whose values can be compared for equality and inequality
using the following class methods
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
All the basic types are instances of the Eq class.
List and Tuples classs are also instances of Eq provided their content types are
instances of Eq
Function types are not instances of Eq.
Ord is the typeclass of Ordered types
All instances of Eq whose values are totally (linearly) ordered.
Can be compared using the following six methods
<, <=, >, >= , which all have type a -> a -> Bool
and min and max which have type a -> a -> a
Strings, Lists and Tuples are ordered lexicographically.
Show is the typeclass of showable types and has a single method
show :: a -> String
Read is the typeclass of types which can be read from strings
read :: String -> a
read "123":: Int
The result of read is undefined if the argument is not syntactically correct
(This can lead to exceptions at run time though the program passes type checking
not (read "False") - OK
not (read "Hello") - NOT OK
Num is the type class of numeric types. Types which are members of Eq and Show
but for which these six methods make sense
(+) ::
(-) ::
(*) ::
abs ::

a ->
a ->
a ->
:: a
a ->
:: a

a -> a
a -> a
a -> a
-> a
-> a

Integral - typeclass for those types that are members of Num but for which inte
division and integer remainder make sense
div :: a -> a -> a
mod :: a -> a -> a
Int and Integer are members of Integral

Fractional - typeclass for those types that are instances of Num for which
fractional division and reciprocation make sense. Float in an instance
(/) :: a -> a -> a
(recip) :: a -> a -> a
Chapter 4 Defining Functions
- conditional expressions
abs :: Int -> Int
abs x = if x >= 0 then x else (-1) * n
- guarded equations
abs :: Int -> Int
abs x | x > 0 = x
| otherwise (-1) * x
- pattern matching
a sequence of syntactic expressions called patterns are used to choose betwee
results of the same type
(&&) :: Bool -> Bool -> Bool
True && True = True
True && False = False
False && True = False
False && False = False
or even better
(&&) :: Bool -> Bool -> Bool
True && True = True
&& _ = False
So far, for pattern matching, we used basic patterns - values, variables, or
wild card
Tuple Matching
A tuple of patterns is itself a pattern which matches any tuple of the same a
rity whose
components all match the corresponding patterns in order
fst :: (a,b) -> a
fst (x,_) = x
Similarly List Matching
A list of patterns is itself a pattern that matches any list of the same arit
whose components all match the corresponding patterns in order. The cons
operator can also be used in pattern matching

to test if a list of any length begins with 'a'

:: [Char] -> Bool
['a':_] = True
_ = False

null [] = True
null (_:_) = False -- note that cons patterns need to be parenthesized

head (x:_) = x
tail (_:xs) = xs -- note that these two functions aren't total. hint []
- lambda expressions
alternate way of creating (anonymous) functions
(\ x -> x + 2 )
(\ x y -> x + y)
1. formalize curried function definitions
add x y = x + y is really add = \x -> (\y -> x + y)
2. are useful to define functions that return functions
const :: a -> b -> a
const x _ = a
is correct but it is better expressed retuning a function
const :: a -> b -> a
const x = \ _ -> x
3. are useful to avoid naming a function
a function odds that returns the first n odd numbers
odds :: Int -> [Int]
odds n = map f [0.. (n-1)]
where f x = x * 2 + 1
works but better is
odds n = map (\ x -> x * 2 + 1) [0 .. (n-1)]
- sections
infix functions are called "operators" (e.g +)
1. any binary function can be converted into an (infix) operator by
placing it between two backticks
2. any operator can be converted into a curried function by placing it
between brackets, thus (+) . This convention also allows one of the
arguments to be included thus giving (1 +) (+ 2) etc
In general given an operator ., (.) (x .) and (. y) are called 'sections
Section meanings can be formalized as below
(*) = \x -> (\y -> x * y)
(x *) = \y -> (x * y)
(* y) = \x -> (x * y)
Sections have three main applications
1. very useful functions like (1+) etc
2. necessary to state the type of (infix) operators, thus
(&&) :: Bool -> Bool -> Bool
3. sections are necessary when treating operators as arguments to functi
e.g : and :: [Bool] -> Bool
and = foldr (&&) True
Chapter 5 Generators

[(x,y) | x <- [1,2,3], y <- [4,5]] gives [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5

Note: rightmost list gets exhausted first
Later generators can depend on variables from earlier generators.
e.g all possible ordered pairings from [1,2,3]
[(x,y) | x <- [1,2,3], y <- [x..3]]
another e.g
concat - that concatenates lists of lists can be written as
concat = [x | xs <- xss, x <- xs]
i.e one generator selects lists (from list of lists) and the next generator
selects elements from the selected list
wildcard patterns can be used to discard elements from a list
length :: [a] -> Int
length xs = sum [1 | _ <- xs]
List comprehensions can use guards to filter the stream
so map a positive integer to its factors
factors x = [y | y <- [1..x], x 'mod' y == 0]
Suppose we implement a lookup table as a list of key value pairs. Then we ca
look up a value (or values) associated with a key by
find :: a -> [(a,b)] -> [b]
find k t = [v | (k',v) <- t, k == k']