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.