考虑:
:type (flip .)
(flip .) :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c
我无法弄清楚原因。据我了解,flip
具有以下类型:
flip :: (a -> b -> c) -> b -> a -> c
此外,(.)
具有以下类型:
(.) :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1
因此,统一我得到的类型:
a = (b1 -> c1) -> (a1 -> b1)
b = a1
给出了:
(flip .) :: a1 -> ((b1 -> c1) -> (a1 -> b1)) -> c1
这与实际类型相差无几。
我做错了什么?任何形式的帮助将不胜感激。
答案 0 :(得分:1)
考虑flip
的类型和函数组成:
flip :: (a -> b -> c) -> b -> a -> c
(.) :: (b -> c) -> (a -> b) -> a -> c
现在,您可以将(.)
应用于flip
,也可以将flip
应用于(.)
。
在第一种情况下:
(flip .)
-- is the same as
(.) flip
-- i.e. you are applying (.) to flip
因此你得到:
flip :: (a -> b -> c) -> b -> a -> c
|___________| |___________|
| |
(.) :: b c -> (a -> b) -> a -> c
-- Hence:
(flip .) :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c
(.) flip :: (a -> a1 -> b -> c) -> a -> b -> a1 -> c
在第二种情况下:
(flip (.))
-- is the same as
flip (.)
-- i.e. you are applying flip to (.)
因此你得到:
(.) :: (b -> c) -> (a -> b) -> a -> c
|______| |______| |______|
| | |
flip :: a b c -> b -> a -> c
-- Hence:
(flip (.)) :: (a -> b) -> (b -> c) -> a -> c
flip (.) :: (a -> b) -> (b -> c) -> a -> c
问题在于,当你写(flip .)
时,Haskell认为它是一个部分。因此,它将flip
视为参数,因为.
是一个运算符。要将运算符视为函数,您需要将其括起来。因此,(flip (.))
被视为将flip
应用于(.)
。在这种情况下,不需要额外的括号集。您只需将其写为flip (.)
。