4

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?

Izbassar Tolegen
  • 1,990
  • 2
  • 20
  • 37
  • 3
    `squareList = map (**2)`. You can "upgrade" a function to work on lists. What's not convenient about that? – Mateen Ulhaq May 19 '19 at 11:11
  • 1
    `map` is also `fmap`. `fmap` is usually thought of as something that "upgrades" functions to work with special types (Functors). – Mateen Ulhaq May 19 '19 at 11:13
  • @MateenUlhaq I don't want to argue about what is convenient or not. I'm curious about the reasoning behind such a decision, that's all. In other languages, the decision is different, which I just get used to. – Izbassar Tolegen May 19 '19 at 11:14
  • 3
    @IzbassarTolegen The reasoning *is* that it's very convenient. – molbdnilo May 19 '19 at 11:18
  • 4
    @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](https://wiki.haskell.org/Parameter_order), [this SO answer](https://stackoverflow.com/questions/31736467/is-there-significance-in-the-order-of-haskell-function-parameters), and [this answer](https://stackoverflow.com/questions/5863128/ordering-of-parameters-to-make-use-of-currying). – bradrn May 19 '19 at 11:20
  • 2
    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 May 19 '19 at 11:56
  • for the function `(>>=)`, a function is its *second* argument, not first. Also for the function `(&)`. – Will Ness May 19 '19 at 15:44

1 Answers1

6

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.

radrow
  • 6,419
  • 4
  • 26
  • 53