### Haskell - lecture 3

-- Here's the filter again, this time with "guards". Guards are like

-- case statements in other languages. The guards are

-- evaluated in order; "otherwise" must come last.

otherFilter :: (a -> Bool) -> [a] -> [a]

otherFilter functionName [] = []

otherFilter functionName (x:xs)

| functionName x = x : otherFilter functionName xs

| otherwise = otherFilter functionName xs

-- This function is intended for use as a filter. It takes one pair

-- as an argument, and returns true if y == 2*x.

-- example use: myFilter doubleSecond [(1,2),(3,4),(5,10)] -> [(1,2),(5,10)]

doubleSecond :: (Int, Int) -> Bool

doubleSecond (x,y)

= y==2 *x

-- Here's another kind of "filter" function: a mapper. It takes a

-- mapping function as an argument, along with a list. It passes

-- each element of the list to the supplied function, and puts the

-- return values in a new list. Example use:

-- myMap (^2) [1,2,3,4] -> [1,4,9,16]

myMap :: (a -> b) -> [a] -> [b]

myMap fn []

= []

myMap fn (x:xs)

= fn x : myMap fn xs

-- The inRange function determines whether a number is

-- in a certain range.

-- The type declaration introduces "Ord". "Ord a" means

-- "any type 'a' that is ordered", i.e. that supports magnitude

-- operators such as > and <. Also notice the new arrow, "=>".

-- It looks like the arrow separates the "interface constraint"

-- on the left with the normal data type declaration on the right.

inRange :: Ord a => a -> a -> a -> Bool

inRange beginning end element

= element >= beginning && element <= end

-- inRange can't be used as a filter directly because it takes 3

-- arguments instead of 1:

-- * myFilter inRange 2 4 [1,2,3,4,5,6] -- wrong

-- However, we can bind the first two arguments, to produce

-- a "new" function that takes only one argument:

-- myFilter (inRange 2 4) [1,2,3,4,5,6] -> [1,5,6]

-- BTW: "zip" takes two lists and makes a list of pairs:

-- zip [1,2,3] ['a','b','c'] -> [(1,'a'),(2,'b'),(3,'c')]

-- zip [1,2,3] "abc" -> [(1,'a'),(2,'b'),(3,'c')]

-- zip [1,2,3,4,5,6] (map (^3) (filter (inRange 2 4) [1,2,3,4,5,6]))

-- -> [(1,8),(2,27),(3,64)]

-- "List comprehensions": a way to generate a finite or infinite

-- list from 1 to 3 parameters. Best explained by example:

-- [1..4] -> [1,2,3,4]

-- [5,4..1] -> [5,4,3,2,1]

-- [5,3.. -5] -> [5,3,1,-1,-3,-5]

-- [2,3.5..7] -> [2.0,3.5,5.0,6.5]

-- [2,3.5..7.5] -> [2.0,3.5,5.0,6.5,8.0] -- strange, eh?

-- [0,10..29] -> [0,10,20]

-- [-2..] -> [-2,-1,0,1,2,...]

-- [2,4..] -> [2,4,6,8,10,12, ...]

-- Here's a list-generating loop construct in Haskell.

ex1 = [x *2 +4 | x <- [1,3..10]]

-- ex1 -> [6,10,14,18,22]

ex2 = [(x,y) | x <- [1..4], y <- [1..4]]

-- ex2 -> [(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4),(3,1),(3,2),(3,3),(3,4),(4,1),(4,2),(4,3),(4,4)]

ex3 = [(x, x*2+y) | x <- [1,2,3], y <- [4,5,6]]

-- ex3 -> [(1,6),(1,7),(1,8),(2,8),(2,9),(2,10),(3,10),(3,11),(3,12)]

tri m = [(i,j) | i <- [0..m], j <- [0..i]]

-- tri 3 -> [(0,0),(1,0),(1,1),(2,0),(2,1),(2,2),(3,0),(3,1),(3,2),(3,3)]

-- :t tri

-- tri :: (Num a, Enum a) => a -> [(a,a)]

-- Tomorrow: computing prime numbers

## 0 Comments:

Post a Comment

<< Home