为什么函数是Haskell中的第一个参数

时间:2019-05-19 11:00:24

标签: haskell functional-programming

我开始学习Haskell。我很好奇为什么在Haskell中将函数作为列表的高阶函数的第一个参数。例如,这里是map的定义:

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

这意味着我可以像这样以前缀或运算符形式使用它:

-- 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])

在Scala中,可以这样写:

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

因此顺序相反,我们将函数作为第二个参数。在Haskell中进行参数排序的原因是什么?

1 个答案:

答案 0 :(得分:6)

这只是一个约定。在大多数情况下,此顺序比相反的用途要有用,因为通常从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 incrflip flipmap incr更好,但是不幸的是Haskell不支持这种类型糖。接下来的事情是,在Scala map中只有一个参数,它“属于”某个列表,因此顺序与Haskell十分相似–不同之处在于目标和功能方法的哲学。