Mentre si lavora la mia strada attraverso le estensioni GHC, mi sono imbattuto in RankNTypes
at the School of Haskell, che ha avuto il seguente esempio:Comprendere RankNTypes Haskell
main = print $ rankN (+1)
rankN :: (forall n. Num n => n -> n) -> (Int, Double)
rankN f = (f 1, f 1.0)
L'articolo ha offerto un tipo alternativo per rankN
:
rankN :: forall n. Num n => (n -> n) -> (Int, Double)
La spiegazione la differenza è che "L'ultima firma richiede una funzione da n a n per alcuni Num n, la prima firma richiede una funzione da n a n per ogni Num n."
Posso capire che il primo tipo richiede che una firma sia tra parentesi o più generale. Non capisco la spiegazione che quest'ultima firma richiede semplicemente una funzione n -> n
per "alcuni Num n
". Qualcuno può elaborare e chiarire? Come si "legge" questa firma precedente in modo che suoni come ciò che significa? La seconda firma è la stessa di semplicemente Num n => (n -> n) -> (Int, Double)
senza la necessità di forall
?
Pensate al corpo della funzione come: '(f (1 :: Int), f (1.0 :: Double))'. Non è possibile utilizzare la seconda firma del tipo per questo. In 'Num n => n -> n -> (Int, Double)' avresti che 'n' deve essere sia' Int' che 'Double' * allo stesso tempo *. Usando '(per tutto il numero n => n -> n) -> (Int, Double)' si ha che la funzione 'f' può essere applicata a diversi tipi e quindi è ben tipizzata. – Bakuriu