Reputation: 1247
I'm currently getting started with Haskell (reading Learn Yourself a Haskell), and came across lines akin to the following:
map (++"!") ["a", "b"] -- ["a!", "b!"]
map ("!"++) ["a", "b"] -- ["!a", "!b"]
Why is this possible, or how does it work? I can't manage to do the same with other non-commutative operations, like division:
map (3/) [1..3] -- [3.0,1.5,1.0]
map ((/)3) [1..3] -- [3.0,1.5,1.0]
map (3(/)) [1..3] -- error
I feel like I'm missing something here, but the implementation of map
doesn't give me any hints.
Upvotes: 4
Views: 506
Reputation: 1803
This code is not valid:
map (3(/)) [1..3]
(/)
is prefix function but you use it as infix. Compiler see it as you try to function 3
(a function without arguments), add (/)
as an argument.
/
is infix function. So, you can do next:
map ( / 3) [1..3] -- [0.3333333333333333,0.6666666666666666,1.0]
map (3 / ) [1..3] -- [3.0,1.5,1.0]
Upvotes: 10
Reputation: 25763
This is not at all related to map; map’s argument can just be any function.
To understand the functions that you have passed, look at this GHCi session:
Prelude> :t (++"!")
(++"!") :: [Char] -> [Char]
Prelude> (++"!") "Hello"
"Hello!"
Prelude> ("!"++) "Hello"
"!Hello"
Prelude> :t ("!"++)
("!"++) :: [Char] -> [Char]
What is happening here is the syntactic idea of operation sections (Haskell report, Sec. 3.4), which can be read as
(x •) == (\y. x • y)
(• x) == (\y. y • x)
where •
can be any operation like ++
, *
or even funny self-defined operators like ^_^
.
Upvotes: 4
Reputation: 5406
If a function is declared in brackets: (++) :: [a] -> [a] -> [a], it can be used with and without them. If used without brackets, they must appear between the arguments: "!" ++ "?"
, but with the brackets they are just like normal functions: (++) "!" "?"
.
Haskell permits "partial application" of functions, so ("!"++)
is the same as (++) "!"
or \x -> (++) "!" x
, and (++"?")
is the same as \x -> (++) x "?"
. ("Partial application" is in quotes, because the functions in Haskell always have just one argument, so application is no longer "partial"; in other languages (++) would be viewed as a function of two arguments, so when only one argument is applied, the function is deemed partially applied - in this sense it may be useful to view ("!"++) as a partially applied (++))
Your second example is a valid way of using (/), but if you use (/), it really is not a infix function anymore, so you get a error attempting to specify the first argument to (/) before the function name: 3(/)
. It still works if you remove the brackets: (3 /)
is the same as ((/) 3)
or (\x -> (/) 3 x)
or (\x -> 3 / x)
Upvotes: 0