Marklar
Marklar

Reputation: 43

Haskell beginner query

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

Answers (3)

S.R.I
S.R.I

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

Daniel Wagner
Daniel Wagner

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

Sebastian Redl
Sebastian Redl

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

Related Questions