Kolja
Kolja

Reputation: 1247

Why can (++) be used both to prepend and append using map?

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

Answers (3)

viorior
viorior

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

Joachim Breitner
Joachim Breitner

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

Sassa NF
Sassa NF

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

Related Questions