Reputation: 43
Hi I have a query about a simple haskell definition. I have a definition but I don't fully understand it.
The function takes in a list of functions and an item and returns a list formed by applying that function.
applyAll = \fs -> \x -> map(\n -> n x) fs
Could somebody explain what n does and why is fs outside the map function?
Upvotes: 1
Views: 362
Reputation: 1870
The function definition:
applyAll = \fs -> \x -> map(\n -> n x) fs
is the same as:
applyAll fs x = map(\n -> n x) fs
Now you might ask, "What are those ->
s doing there if they are just arguments to my function applyAll
. Haskell has no concept of multi-param functions. What you see as multiple arguments to a function is just many functions chained together each with a single argument. In the case of applyAll
, it's just two functions chained together:
(applyAll fs) -> x = map (\n -> n x) fs
applyAll fs
is one function chained to another argument identified as x
to yield a list of values returned by map
.
I could try this out in ghci:
Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs
<interactive>:1:10: Not in scope: `xs'
Prelude> let xs = [1..5]
-- hah, BOOM! I told you haskell's strongly typed...
Prelude> :t applyAll xs
<interactive>:1:10:
Couldn't match expected type `t0 -> b0' with actual type `Integer'
Expected type: [t0 -> b0]
Actual type: [Integer]
In the first argument of `applyAll', namely `xs'
In the expression: applyAll xs
Prelude> let xs = [(1 +), (2 +), (3 *), (4 /)]
Prelude> :t xs
xs :: [Double -> Double]
Prelude> :t applyAll xs
applyAll xs :: Double -> [Double]
Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs 3
applyAll xs 3 :: [Double]
Prelude> applyAll xs 3
[4.0,5.0,9.0,1.3333333333333333]
What's the type of map
?
map :: (a -> b) -> [a] -> [b]
This tells me that map
takes a function - let's call it f
and a list of values to return another list of values. The function f
is one that takes a value of type a
returning another of type b
. So map
goes on applying f
to each value in the list [a]
to return another list filled with values of type b
.
In your applyAll
, the function f
is \n -> n x
. This is a lambda expression(you might call it an anonymous function) taking a value identified by n
and applying x
to it. This goes on for every item in the input list identified by [a]
in the type definition until it runs out to yield another list identified by [b]
in the type definition.
Upvotes: 2
Reputation: 152682
Here's a simple function definition:
f x = 2*x + 1
This creates a new function f
, which takes one argument. You could use it later like this:
main = print (f 3)
...which would print 7. Sometimes, it is convenient to define a function without giving it a name. The syntax for that is \{- argument -} -> {- function body -}
; for example, we could do an anonymous version of f
above this way:
main = print ((\x -> 2*x + 1) 3)
Now, your definition of applyAll
is just doing this several times. We could explicitly name everything in where
clauses if we wanted:
applyAll = outerMost where
outerMost fs = mapApply where
mapApply x = map applyToX fs where
applyToX n = n x
...though I think you'll agree that the extra verbosity doesn't make things much more clear! A more natural (but less mechanical) translation away from anonymous functions would look like this:
applyAll fs x = map applyToX fs where
applyToX n = n x
and now hopefully this can very nearly read like English: to apply all the functions fs
to a single value x
, we map "the function that applies a single function (which we temporarily name n
) to the value x
" over the list of all functions.
Upvotes: 0
Reputation: 71899
The spacing is misleading you. It looks like map(\n -> n x)
is a function call, but the parentheses here are for grouping, not function call. map
takes two arguments; the full call is map (\n -> n x) fs
, where (\n -> n x)
is the first argument (a lambda expression) and fs
is the second.
The lambda \n -> n x
is a function that takes a function as an argument and returns the result of applying that function to x
. n
is the argument here. The type of \n -> n x
is (a -> b) -> b
(where a
is the type of x
). If you have learned about sections yet, the lambda is equivalent to the section ($ x)
. If you haven't, ignore that last sentence.
Upvotes: 8