了解具有功能组合的地图功能

时间:2019-06-14 07:41:09

标签: haskell functional-programming higher-order-functions

我有以下Haskell表达式:

let increment x = 1 + x
in \xs -> map chr (map increment (map ord xs))

我知道上面的表达式接受一个列表,并将ord函数应用于列表中的每个元素。对于字符列表,结果将是整数列表(ASCII值)。然后,increment函数将列表中的每个整数递增1。chr函数随后将每个整数转换回其对应的字符。

我还有以下表达式:

map chr . map (1+) . map ord

我试图弄清楚以上内容是否等同于第一个表达式。 但是,当我在GHCI中尝试上述表达式时,出现错误:

map chr . map (1+) . map ord ['a', 'b', 'c', 'd', 'e']

我不确定为什么该表达式不起作用。由于使用了函数组合,因此表达式的计算结果不会为:

(map chr (map (1+) (map ord ['a', 'b', 'c', 'd', 'e'])))

map (1+)由于map ord而获得列表,而map chr由于map (1+)而得到列表吗?

1 个答案:

答案 0 :(得分:5)

运算符(定义为名称中没有字母数字字符的函数,以infix样式使用)的优先级低于Haskell中的其他函数。因此你的表情:

map chr . map (1+) . map ord ['a', 'b', 'c', 'd', 'e']

解析为:

(map chr) . (map (1+)) . (map ord ['a', 'b', 'c', 'd', 'e'])

这没有任何意义-.运算符组合了两个函数,而map ord ['a', 'b', 'c', 'd', 'e']不是一个函数,而是一个数字列表。

但是,对于带有所有嵌套括号的正确版本,还有更好的替代方法。您想要做的是从字符列表开始,并依次在其上map 3个功能。根据函数组成的定义,这与对其应用3个map的组成相同,即:

(map chr . map (1+) . map ord) ['a', 'b', 'c', 'd', 'e']
@chi指出的

经常使用函数应用程序运算符$(其优先级低于任何其他运算符)来编写,以避免使用括号:

map chr . map (1+) . map ord $ ['a', 'b', 'c', 'd', 'e']

而且,因为map f . map g始终与map (f . g)相同(当您停止思考这些表达式的含义时,这很明显-这也是map操作必须遵循的基本定律为了使列表类型成为Functor),可以这样写:

map (chr . (1+) . ord) ['a', 'b', 'c', 'd', 'e']

我认为这是最好,最易读的版本。

更好的是,正如@chi再次指出的那样,是使用chr . (1+) . ord等同于succ,这是一种内置函数,用于获取可以枚举。因此,您只需编写map succ ['a', 'b', 'c', 'd', 'e']