3
votes

I started to learn Haskell. I'm curious about why in Haskell the function is taken as the first argument for the higher order functions for lists. For example here is a definition of map:

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

It means that I can use it either in prefix or operator form like that:

-- yields [3,5,7]
map (+ 2) [1,3,5]
-- we can chain like that
filter (< 4) (map (+ 2) [1,3,5])

-- or in operator form 
(+ 2) `map` [1,3,5]
(< 4) `filter` ((+ 2) `map` [1,3,5])

In Scala the same can be written as follows:

List(1,3,5) map (_ + 2)
// we can chain as follows:
List(1,3,5) map (_ + 2) filter (_ < 4)

So the order is reversed and we take the function as the second argument. What is the reason on arguments ordering in Haskell?

1
squareList = map (**2). You can "upgrade" a function to work on lists. What's not convenient about that?Mateen Ulhaq
map is also fmap. fmap is usually thought of as something that "upgrades" functions to work with special types (Functors).Mateen Ulhaq
@IzbassarTolegen The reasoning is that it's very convenient.molbdnilo
@IzbassarTolegen In fact, for many functions in Haskell, the only reason for their argument order is convenience. For more details on argument order, see HaskellWiki, this SO answer, and this answer.bradrn
In Scala the function isn't the second argument to map - it's the only argument to map. The function couldn't be on the left of the method name because then you'd be calling map on the function object, not on the list, and functions don't have a method named map.sepp2k

1 Answers

6
votes

It is just a convention. This order is in most cases more useful than the opposite, because usually from Data.List library you would rather expect utilities that will allow you to "transform given list" than "describe how to transform some fixed list".

Check this case:

f :: [Int] -> [Int]
f = map (+1)

Here f Is a function that increments all elements of any Int list. It could be called incrAll and it would sound more flexible than

g :: (Int -> a) -> [a]
g f = map f [1,2,3] 

that is fixed to work on this particular [1,2,3] list. Of course, it may find some usage but it is less likely in general. f after single application is still a function that "works on lists".

As I know Scala you may write something like f = _.map(incr) which is way nicer than (assuming flipmap = flip map) \l -> flipmap l incr or flip flipmap incr, but unfortunately Haskell does not support this kind of sugar. Next thing is that in Scala map has just one argument and it "belongs" to some list, so the order is quite similar to Haskell – the difference is in the philosophy of objective and functional approaches.