【问题标题】:Why function is the first argument in Haskell为什么函数是 Haskell 中的第一个参数
【发布时间】:2019-05-19 11:00:24
【问题描述】:

我开始学习 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 中参数排序的原因是什么?

【问题讨论】:

  • squareList = map (**2)。您可以“升级”功能以处理列表。那有什么不方便的?
  • map 也是fmapfmap 通常被认为是“升级”函数以使用特殊类型(函子)。
  • @IzbassarTolegen 理由非常方便。
  • @IzbassarTolegen 实际上,对于 Haskell 中的许多函数,它们的参数顺序的唯一原因是方便。有关参数顺序的更多详细信息,请参阅HaskellWikithis SO answerthis answer
  • 在 Scala 中,函数不是 map 的第二个参数 - 它是 map 的唯一参数。该函数不能位于方法名称的左侧,因为这样您将在函数对象上调用map,而不是在列表中,并且函数没有名为map 的方法。

标签: haskell functional-programming


【解决方案1】:

这只是一个约定。在大多数情况下,此顺序比相反的顺序更有用,因为通常来自 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 在单个应用程序之后仍然是“适用于列表”的功能。

据我所知,您可以编写类似f = _.map(incr) 的东西,这比(假设为flipmap = flip map\l -&gt; flipmap l incrflip flipmap incr 好得多,但不幸的是,Haskell 不支持这种糖。接下来的事情是,在 Scala 中,map 只有一个参数,并且它“属于”某个列表,因此顺序与 Haskell 非常相似——不同之处在于目标方法和函数方法的哲学。

【讨论】:

    猜你喜欢
    • 2017-01-25
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多