==可以在元组上使用,也就是你可以写(a1, b1) == (a2, b2).
在这种情况下,类型==是专门的(Eq a, Eq b) => (a, b) -> (a,b) -> Bool.
如果你现在适用curry于那种类型,你会得到(Eq a, Eq b) => a -> b -> (a, b) -> Bool.
定义curry是:
curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x y -> f (x, y)
Run Code Online (Sandbox Code Playgroud)
如果我们用以下代替:
\x y z -> (curry (==) x y) z
\x y z -> ((==) (x, y)) z -- Function application
\x y z -> (==) (x, y) z -- Remove parentheses (function application is left associative in Haskell, so they are unnecessary here)
\x y z -> (x, y) == z -- Convert to infix
Run Code Online (Sandbox Code Playgroud)
我们可以立即告诉它z必须是某种元组,否则最后一行不会进行类型检查,因为两个参数==必须具有相同的类型.
当我们查看元组实例的定义时Eq,我们发现
instance (Eq a, Eq b) => Eq (a, b) where
(x, y) == (x', y') = (x == x') && (y == y')
Run Code Online (Sandbox Code Playgroud)
(这不是在标准库的源代码中拼写出来的,它实际上使用"独立派生"机制来自动派生(Eq a, Eq b) => (a, b)类型的实例.这段代码等同于派生的内容.)
因此,在这种情况下,我们可以将其==视为具有类型
(==) :: (Eq a, Eq b) => (a, b) -> (a, b) -> Bool
Run Code Online (Sandbox Code Playgroud)
双方x并y必须是实例类型Eq,但他们并不需要是相同的实例Eq.例如,如果我们有12和"abc"?这是两种不同的类型,但我们仍然可以使用我们的函数,因为它们都是Eq:( (\x y z -> (x, y) == z) (12, "abc") (30, "cd")此表达式类型检查和求值False).