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
andnumerator
in the expression:divBy numerator = map (numerator `div`)
What values ββare the variables divBy
and numerator
assigned at the end?
-
map
Function typemap :: (a -> b) -> [a] -> [b]
. In the above expression, the argument isnumerator
not a function type, and isdiv
not an array type. But the code works!
What am I missing here?
source to share
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 isnumerator
not a function type, and isdiv
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.
source to share
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 expressionmap (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 argumentmap
isxs
definitely a list, as it should be. The first argumentmap
,(numerator `div`)
must be of type functiona -> a
, wherea
- is the type that is an instanceIntegral
. 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 typeIntegral 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.
source to share