4

我目前正在开始使用 Haskell(阅读 Learn Yourself a Haskell),并且遇到了类似于以下内容的行:

map (++"!") ["a", "b"] -- ["a!", "b!"]
map ("!"++) ["a", "b"] -- ["!a", "!b"]

为什么这是可能的,或者它是如何工作的?我无法对其他非交换操作做同样的事情,比如除法:

map (3/) [1..3]   -- [3.0,1.5,1.0]
map ((/)3) [1..3] -- [3.0,1.5,1.0]
map (3(/)) [1..3] -- error

我觉得我在这里遗漏了一些东西,但实施map并没有给我任何提示。

4

3 回答 3

10

此代码无效:

map (3(/)) [1..3]

(/)是前缀函数,但您将其用作中缀。编译器会在您尝试运行时看到它3(没有参数的函数),添加(/)为参数。

/是中缀函数。因此,您可以执行以下操作:

map ( / 3) [1..3]   -- [0.3333333333333333,0.6666666666666666,1.0]
map (3 / ) [1..3]   -- [3.0,1.5,1.0]
于 2013-09-20T11:09:24.067 回答
4
于 2013-09-20T11:20:35.893 回答
0

如果函数在括号中声明:(++) :: [a] -> [a] -> [a],则可以使用或不使用它们。如果不使用括号,它们必须出现在参数之间:"!" ++ "?",但使用括号它们就像普通函数:(++) "!" "?"

Haskell 允许函数的“部分应用”,因此("!"++)(++) "!"or相同\x -> (++) "!" x,并且(++"?")\x -> (++) x "?". (“部分应用程序”是带引号的,因为 Haskell 中的函数总是只有一个参数,所以应用程序不再是“部分”;在其他语言中(++)将被视为两个参数的函数,所以当只有一个参数时参数被应用,函数被视为部分应用 - 从这个意义上说,将 ("!"++) 视为部分应用 (++))

您的第二个示例是使用 (/) 的有效方式,但如果您使用 (/),它实际上不再是中缀函数,因此您尝试在函数名称之前指定 (/) 的第一个参数时会出错:3(/). 如果您删除括号它仍然有效:与or or(3 /)相同((/) 3)(\x -> (/) 3 x)(\x -> 3 / x)

于 2013-09-20T11:20:33.423 回答