Haskell - fmap fmap non funziona
Domanda
Sto usando GHCi (versione 6.12.3) per giocare un po 'con Haskell.Recentemente ho letto di funtori e funtori applicativi pensato che se non si potesse implementare qualcosa di simile al <*>
dei funtori applicativi utilizzando solo le primitive del funtore.Dopo averci pensato un po ', mi è venuto in mente fmap fmap
che avrebbe un tipo (quasi) ideale di
Functor f => f (a -> b) -> f (f a -> f b)
o più genericamente
(Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b)
Ho provato
let q = fmap fmap
Ho ricevuto il seguente errore
<interactive>:1:8:
Ambiguous type variable `f1' in the constraint:
`Functor f1' arising from a use of `fmap' at <interactive>:1:8-16
Probable fix: add a type signature that fixes these type variable(s)
<interactive>:1:13:
Ambiguous type variable `f' in the constraint:
`Functor f' arising from a use of `fmap' at <interactive>:1:13-16
Probable fix: add a type signature that fixes these type variable(s)
Scrivere la firma del tipo sopra come suggerito non ha aiutato.
La cosa più pazza è che quando ho digitato :t fmap fmap
ho ottenuto un tipo equivalente come sopra.
Cosa sto facendo di sbagliato?Perché fmap fmap
restituisce un errore di tipo sebbene GHCi trovi un tipo per esso?
Soluzione
Sembra che tu stia incappando nella restrizione sul monomorfismo .
Provare il tuo esempio in GHCi con -XNoMonomorphismRestriction
fornisce il risultato atteso.
Puoi anche sovvertirlo scrivendo let f x = fmap fmap $ x
.La restrizione sul monomorfismo si applica solo alle definizioni di primo livello che "assomigliano" a valori, ad esempio f = something
, quindi l'introduzione di un argomento esplicito fa sì che non si applichi più.Inoltre, non si applicherebbe se questo non fosse al livello più alto (ad esempio in una clausola where
).Per ulteriori dettagli, vedere il collegamento.
Altri suggerimenti
Non posso ancora commentare ovunque, quindi posterò una risposta.Come accennato in precedenza, l'errore che stai ricevendo è dovuto alla restrizione del monomorfismo.Fissare la firma del tipo a uno dei due dati nella domanda originale rende effettivamente ghci felice come speravi, forse hai appena sbagliato la sintassi?
Prelude> let q :: (Functor f) => f (a -> b) -> f (f a -> f b); q = fmap fmap Prelude> :t q q :: (Functor f) => f (a -> b) -> f (f a -> f b) Prelude> let q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b); q = fmap fmap Prelude> :t q q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b)