为什么(++)可以用于使用map进行前置和附加?

时间:2013-09-20 11:04:33

标签: haskell functor

我目前正在开始使用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的实施并没有给我任何提示。

3 个答案:

答案 0 :(得分: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]

答案 1 :(得分:4)

这与地图完全无关; map的参数可以是任何函数。

要了解您已经通过的功能,请查看此GHCi会话:

Prelude> :t (++"!")
(++"!") :: [Char] -> [Char]
Prelude> (++"!") "Hello"
"Hello!"
Prelude> ("!"++) "Hello"
"!Hello"
Prelude> :t ("!"++)
("!"++) :: [Char] -> [Char]

这里发生的是操作部分(Haskell report,Sec.3.4)的句法概念,可以理解为

(x •) == (\y. x • y)
(• x) == (\y. y • x)

其中可以是++*等任何操作,甚至是^_^等有趣的自定义运算符。

答案 2 :(得分:0)

如果在括号中声明了一个函数:(++):: [a] - > [a] - > [a],可以使用和不使用它们。如果在没有括号的情况下使用它们,它们必须出现在参数"!" ++ "?"之间,但使用括号它们就像普通函数一样:(++) "!" "?"

Haskell允许“部分应用”函数,因此("!"++)(++) "!"\x -> (++) "!" x相同,(++"?")\x -> (++) x "?"相同。 (“部分应用程序”在引号中,因为Haskell中的函数总是只有一个参数,因此应用程序不再是“部分”;在其他语言中(++)将被视为两个参数的函数,因此当只有一个时如果应用了参数,则该函数被视为部分应用 - 在这种意义上,将(“!”++)视为部分应用(++)可能是有用的。

你的第二个例子是使用(/)的有效方法,但是如果使用(/),它实际上不再是一个中缀函数,所以你在尝试指定(/)之前的第一个参数时会出错。功能名称:3(/)。如果您删除括号,它仍然有效:(3 /)((/) 3)(\x -> (/) 3 x)(\x -> 3 / x)

相同