Map function takes non-function as first argument

-- file: ch19/divby1.hs
divBy :: Integral a => a -> [a] -> [a]
divBy numerator = map (numerator `div`)

      

This is a code snippet from O'Reilly-Haskell's book.

sample run as,

ghci> divBy 50 [1,2,5,8,10]
[50,25,10,6,5]

      

What confuses me

  • why are there two variables on the LHS divBy

    and numerator

    in the expression:

    divBy numerator = map (numerator `div`)
    
          

What values ​​are the variables divBy

and numerator

assigned at the end?

  1. map

    Function type map :: (a -> b) -> [a] -> [b]

    . In the above expression, the argument is numerator

    not a function type, and is div

    not an array type. But the code works!

What am I missing here?

+3


source to share


2 answers


by eta transformations and signatures

At first I think you missed a bit `

: in numerator `div`

(yes, I think SO ate them - you have to inject this as `` numerator `div` ``

it works!)

It:

divBy :: Integral a => a -> [a] -> [a]
divBy numerator = map (numerator `div`)

      

- another way to record

divBy :: Integral a => a -> [a] -> [a]
divBy = \ numerator -> map (numerator `div`)

      

which can be decomposed into

divBy :: Integral a => a -> [a] -> [a]
divBy = \ numerator ns -> map (numerator `div`) ns

      

if you want the arguments to return to the left afterwards:

divBy :: Integral a => a -> [a] -> [a]
divBy numerator ns -> map (numerator `div`) ns

      

and here it might be clearer what numerator

is the first argument (of type a

) and what is the ns

second (of type [a]

) and divBy

is of course the name of the function.

This works because there is something called eta conversion that basically says that you can shorten \x -> f x

to f

- but don't look sometimes you run into a problem with this, but often used point-free-style to write Haskell code ...

your questions

What confuses me

why are there two variables in LHS divBy and a numerator in the expression:



divBy numerator = map (numerator `div`)

      

Answer : These are not variables - the first is the name of the function you are declaring on that line, and the second is the name for the first argument.

You may be wondering where the second one went (see above) - short answer: divBy

- indeed a function that takes a

and returns another function [a] -> [a]

and so there is only one argument that you have to give while you return the function (and you do ).

What values, divBy variables and the numerator are assigned at the end?

Answer . As I said divBy

- this is the name for your function - numerator

will receive the first argument, so in

 Ξ»> divBy 5 [1..10]
 [5,2,1,1,1,0,0,0,0,0]

      

numerator

is an 5

Map Function Type map :: (a -> b) -> [a] -> [b]

In the above expression, the argument is numerator

not a function type, and is div

not an array type. But the code works !!

What am I missing here?

Basically you are missing the parentheses - (numerator `div`)

it's the so-called section - it really is a function \n -> numerator `div` n

- think of it as having a hole in the second argument of the infix `div`

: (disclaimer: pseudocode) (numerator `div` _)

.

So, it (numerator `div`)

really is a function Integral a => a -> a

and therefore matches the first argument map

.

Now where is the second? Well, again, this is the same story as above: map (numerator `div`)

is a function Integral a => [a] -> [a]

, and it was not for the right side of your declaration divBy numerator

.

I hope you can understand what I gave you in the first part of this answer.

If you have a question leave a comment - I will try to add explanations where necessary.

+4


source


I would read this code like this:

The type divBy

says it takes two arguments [1], a a

and a [a]

, but the LHS of its declaration only shows one argument, viz numerator

. So let me add the second argument myself to complete the image:

divBy numerator xs = map (numerator `div`) xs

Note that I used the name xs

(read x-es, as in "more than one x") because the second argument is a list. I could use, say, x

instead, but using xs

is a visual reminder that a thing is a list and helps a lot to avoid confusion later on.



Everything looks a little clearer now:

  • A statement divBy numerator xs

    is exactly the same as an expression map (numerator `div`) xs

    : wherever I see the first expression, I can replace it with the last expression.
  • map (numerator `div`) xs

    looks good enough to me: the second argument map

    is xs

    definitely a list, as it should be. The first argument map

    , (numerator `div`)

    must be of type function a -> a

    , where a

    - is the type that is an instance Integral

    . That is, it (numerator `div`) :: Integral a => a -> a

    must be fulfilled. So now I only have to worry about why it would be like that.
  • I am trying to understand why it (numerator `div`)

    has a type Integral a => a -> a

    . Other answers have explained why this is the case and I am happy!

[1] To be pedantic, divBy

only takes one argument, etc., but now I am pedagogy.

+1


source







All Articles