我有以下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+)
而得到列表吗?
答案 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']