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