Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using map in Haskell

I want to use map to substract the average of a list from each element of a list using map. So far I got this function for calculating the average:

averageOfList :: [Float] -> Float
averageOfList [] = 0
averageOfList a = ((foldl (+) 0 a) / fromIntegral(length a))

The list is [1.3,1.7,3.3,1.0,3.3]. How exactly do I use the function for the average in map to subtract from each element?

like image 764
Hello there Avatar asked Dec 31 '22 11:12

Hello there


1 Answers

For people new to functional programming map may be one of the first concepts that they struggle with. map is a function that takes two parameters: a function and a list of elements.

The type signature of map is (a -> b) -> [a] -> [b]. The (a -> b) part is the function you pass to map, we will call it f. f takes one value and returns another that may be of a different type. The [a] part is the list of elements you want to apply f to, we will call it xs. Notice how the type signature of f takes an a and the type signature of xs is [a], the type that f takes must match the type of elements in xs. The other thing to notice is the return type of map is [b]. This matches the return type of f.

Here is a simple example of using map.

plusOne :: Int -> Int
plusOne x = x + 1

xs = [1,2,3,4,5,6]
ys = map plusOne xs

In this case the a type in map will be Int and the b type in map will also be Int. Let's look at a case where a and b types are different.

-- show :: a -> String
zs = map show ys

In this case a is Int and b is String. We get back a list of String. If you are familiar with a language like Python or C, you have probably made a for loop that starts at 0 and goes to the end of the array's length and changed the elements inside. This is the same concept.

Finally, to answer your main question, you need to first apply averageOfList to a [Float], then subtract the resulting average from each element in a list.

avg = averageOfList [1.3,1.7,3.3,1.0,3.3]

subAvg x = x - avg

map subAvg [0.0,2.0,3.4,5.6]

In this example above I have written out the name and definition of a function we want to map over a list of floats. Another strategy is define a function inline without using a name (this is called a lambda function or anonymous function).

map (\x -> x - avg) [0.0,2.0,3.4,5.6]

The syntax (\x -> ) means define a function that takes one parameter and we will call it x, then we define a body for the function. This is a way to define a function in line and without giving it a name.

like image 109
MCH Avatar answered Jan 10 '23 23:01

MCH