我了解到可以通过两种方式调用函数:前缀和中缀。例如,假设我创建了此函数:
example :: [Char] -> [Char] -> [Char]
example x y = x ++ " " ++ y
我可以这样称呼它为前缀:
example "Hello" "World"
或像这样的中缀:
"Hello" `example` "World"
这两者都会导致表示字符串"Hello World"
的字符列表。
但是,我现在正在学习有关函数组成的知识,并且遇到了如下定义的函数:
(.) :: (b -> c) -> (a -> b) -> a -> c
所以,说我想乘以3来求和。我会像这样写前缀调用:
negateComposedWithMultByThree = (.) negate (*3)
和infix调用类似:
negateComposedWithMultByThree = negate `(.)` (*3)
但是,虽然前缀调用可以编译,但infix调用却不会,而是显示错误消息:
错误:解析输入`('
时的错误
看来,要调用撰写中缀,我需要省略方括号并这样称呼它:
negateComposedWithMultByThree = negate . (*3)
任何人都可以阐明这一点吗?为什么"Hello" `example` "World"
却没有negate `(.)` (*3)
?
此外,如果我尝试使用这样的签名来实现自己的功能:
(,) :: Int -> Int
(,) x = 1
它无法编译,并显示错误:
“无效的类型签名(,):...的形式应为::”
答案 0 :(得分:13)
这里没有深处。关于标识符的解析,只有两种标识符具有不同的规则:by-default-infix和by-default-prefix。您可以分辨出是哪一个,因为默认前缀标识符仅包含标点符号,而默认前缀标识符仅包含数字,字母,撇号和下划线。
认识到默认并非总是正确的选择,该语言提供了与默认行为不同的转换。因此,有两种单独的语法规则,一种将默认的前缀标识符转换为前缀(添加括号),另一种将默认的前缀标识符转换为中缀(添加反引号)。您不能嵌套这些转换:转换为前缀形式的默认前缀标识符不是默认前缀标识符。
就是这样。根本上没有什么有趣的-解析后它们全部成为函数应用程序-只是语法糖。