Transcript Lecture 5
Functional Programming
Lecture 5 - Tuples
Packaging several values together
Sometimes you need to package up several values into
a single object
– A function returns one value, but
what if you have several values to
return?
– Several data values are
used together; it is logical to treat the entire
collection as one object.
Tuples
• (2,3) :: (Int,Int)
– a pair or a 2-tuple
• (2, “dog”) :: (Int, String)
– a pair or a 2-tuple
• (“Calder”,”Monday”,[9,11,14])
:: (String, String,[Int])
– a triple or a 3-tuple
• (pi, times2) :: (Double, Int->Int)
– where times2 x = x * 2
• ( ) :: ( )
– a 0-tuple (sometimes used as a dummy value)
You can have n-tuples for any n.
x1 :: T1 … xn :: Tn
(x1,…,xn) :: (T1,…Tn)
What is type of (2,3)?
What is type of (2,”dog”)?
Convention, (5,6) is a pair, (Int,Int) is a Pair.
Tuples vs. Lists
Similarities:
Both package up several values into one.
Both are type constructors.
Differences:
Tuple:
fixed number of components,
the components may have different types.
(3,4) :: (Int,Int)
(3,”hello”) :: (Int,[Char])
List:
any number of elements,
the elements must have the same type.
[3,4] ::[Int]
[3,”hello”] :: type error
Example: Cross Product
Represent sets A and B as lists.
mathematics
A B = {(x,y) | x A, y B}
Haskell
crossProd :: [a] -> [b] -> [(a,b)]
crossProd xs ys
= [(x,y) | x <- xs, y <- ys]
crossProd “abc” [1..3] =>
[(‘a’,1), (‘a’,2), (‘a’,3), (‘b’,1), (‘b’,2), (‘b’,3),
(‘c’,1), (‘c’,2), (‘c’,3)]
Example: A Database
A database holds information about employees.
type Item = (String, String, String, Int, Int)
-- (name, address, postcode, age, salary)
type Database = [Item]
ex1 = [(“Smith”, “Byres”, “G12 8QQ”, 30, 30000),
…..
Database queries
Make a mailing label for every employee under 30 who is
making at least 30k per year, and who lives within the G1
postcode area.
labels :: Database -> [String]
labels db =
[n ++ “\n” ++ a ++ “\n”
| (n,a,p,o,s) <- db, o<30, s>=30000, take 3 p == “G1_”]
(n,a,p,o,s) is called a pattern.
Note difference between `\n’ and “\n”
Returning several results
Example: Quadratic Equation
Quadratic equation
ax2 + bx + c = 0
has two solutions
(- b (b2 - 4ac)) / 2a.
We would like a function that solves the equation
properly, and returns both solutions
Note - in some cases there are complex
solutions - we will ignore these.
Example: Quadratic Equation
quadratic :: Double -> Double -> Double
-> (Double,Double)
3 arguments and one result which is a pair
quadratic a b c = (x1, x2)
where
x1 = (-b + d) / (2*a)
x2 = (-b - d) / (2*a)
d = sqrt (b^2 - 4*a*c)
or
quadratic a b c =
let d = sqrt (b^2 - 4*a*c)
x1 = (-b + d) / (2*a)
x2 = (-b - d) / (2*a)
in (x1, x2)
A note about floating point
It is not always exact
0.11 - 0.10 => 0.01 :: Double
but
2.11 - 2.10 => 0.00999999 :: Double
This is not an error.
It is a property of floating point, not of Haskell.
You must be careful with floating point, as in any
programming language.
Rounding
• It is possible to round the numbers
0.00999999 => 0.01
• But rounded output DOES NOT affect
the number actually represented, it gives only the
illusion that the number is exactly correct.
Comparison of floating point
• It may be unsafe to use == to compare two
floating point numbers
– if 0.11-0.10 == 2.11-2.10
then should get this result
else but you’ll get this result instead
• It does not make any difference if the
output is printed in rounded form the internal computation will be wrong.
• This is true for all programming languages
When should floating point
be used?
The input data already has some imprecision
data measured in an experiment.
You expect an approximate result,
and you know what the “error tolerance” is.
The result may be big (astronomical)
or small (microscopic), and it would be
written in scientific notation.
Do not use floating point for money!