Это просто соглашение.Этот порядок в большинстве случаев более полезен, чем противоположный, потому что обычно от Data.List
библиотеки вы скорее ожидаете утилит, которые позволят вам «преобразовать заданный список», чем «описать, как преобразовать некоторый фиксированный список».
Проверьте этот случай:
f :: [Int] -> [Int]
f = map (+1)
Здесь f
Функция, которая увеличивает все элементы любого списка Int
.Его можно назвать incrAll
, и он будет звучать более гибко, чем
g :: (Int -> a) -> [a]
g f = map f [1,2,3]
, который предназначен для работы с этим конкретным списком [1,2,3]
.Конечно, это может найти какое-то применение, но в целом оно менее вероятно.f
после одного приложения - функция, которая «работает со списками».
Как я знаю, Scala вы можете написать что-то вроде f = _.map(incr)
, что намного лучше, чем (при условии flipmap = flip map
) \l -> flipmap l incr
или flip flipmap incr
, но, к сожалению, Haskell не поддерживает этот вид сахара.Следующее, что в Scala map
есть только один аргумент, и он «принадлежит» к какому-то списку, поэтому порядок очень похож на Haskell - разница в философии объективного и функционального подходов.