La definizione di curry
è:
curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x y -> f (x, y)
Se sostituiamo che:
\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
Possiamo dire subito che z
deve essere un qualche tipo di tupla, altrimenti quest'ultima riga non avrebbe digitato il check poiché entrambi gli argomenti di ==
deve avere lo stesso tipo.
Quando guardiamo la definizione dell'istanza tupla per Eq
, troviamo
instance (Eq a, Eq b) => Eq (a, b) where
(x, y) == (x', y') = (x == x') && (y == y')
(Questo non è scritto nel codice sorgente della libreria standard, in realtà utilizza il "derivante standalone" meccanismo per derivare automaticamente l'istanza per il tipo (Eq a, Eq b) => (a, b)
. questo codice è equivalente a quello che viene derivato però.)
Quindi, in questo caso, si può trattare ==
come se ha il tipo
(==) :: (Eq a, Eq b) => (a, b) -> (a, b) -> Bool
Sia x
e y
deve avere tipi che sono le istanze di Eq
, ma non hanno bisogno di essere l'istanza stesso di Eq
. Ad esempio, cosa succede se abbiamo 12
e "abc"
? Sono due tipi diversi, ma possiamo ancora utilizzare la nostra funzione, poiché sono entrambe le istanze di Eq
: (\x y z -> (x, y) == z) (12, "abc") (30, "cd")
(questo tipo di espressione controlla e valuta False
).
Ok, ma come hai capito che il == è stato applicato alle tuple? – Fof
@Seba Perché 'curry' si aspetta una funzione il cui primo argomento è una tupla. – sepp2k