Come si può usare id (a -> a) come il primo parametro da mantenere, che richiede una funzione (a -> b -> c)?
realtà, uncurry
richiede (a -> (b -> c))
funzione. Riesci a individuare la differenza? :)
L'omissione delle parentesi è malvagia (bene, a volte). Rende impossibile a un principiante decifrare Haskell. Ovviamente dopo aver raccolto qualche esperienza con la lingua, ti senti come se non avessi più bisogno di loro.
Qui, tutto diventa chiaro una volta che scriviamo tutte le parentesi omessi indietro in modo esplicito:
uncurry :: (a -> (b -> c)) -> ((a,b) -> c)
id :: a -> a
Ora, scrivendo uncurry id
chiede un tipo di unificazione a1 -> a1
con a2 -> (b -> c)
. Questo è semplice, a1 ~ a2
e a1 ~ (b -> c)
. Solo materiale meccanico, , nessun pensiero creativo ha coinvolto qui. Quindi id
in questione ha effettivamente il tipo a -> a where a ~ (b -> c)
e quindi uncurry id
ha il tipo (b -> c,b) -> c
, con la semplice sostituzione di a ~ (b -> c)
in (a,b) -> c
. Vale a dire, prevede una coppia di una funzione b -> c
e un valore b
e deve produrre un valore c
.
Dal momento che i tipi sono più generale (vale a dire non si sa nulla di loro, e quindi non c'è nessun funzioni specifiche per chiamare che potrebbe fare il trucco in qualche modo speciale), il unico modo per produrre un valore c
qui è quello di chiama la funzione b -> c
con il valore b
come argomento. Naturalmente, questo è ciò che fa ($)
. Quindi uncurry id == uncurry ($)
, anche se id
è sicuramente non($)
.
fonte
2012-01-20 12:40:17
Grazie! Inizia a dare un senso! Lo trovo ancora un po 'spinout! – ssanj
@ssanj: Se c'è qualche consolazione, scrivendo questo come "id non corretto" piuttosto che "uncurry ($)" è male :) – ehird
E se vuoi essere particolarmente malvagio, potresti scrivere '(\' id \ '3) 'invece di' ($ 3) 'o definisci' id' come 'infixr 0 \' id \ '' e usalo al posto di '($)', come '(^ 2) \' id \ '1 + 2 * 3'. – Vitus