Mi sono imbattuto in un frustrante qualcosa di in Haskell oggi.Errore di tipo strano in Let-expression di Haskell: qual è il problema?
Ecco cosa è successo:
- ho scritto una funzione in ghci e lo diede una firma tipo
- ghci lamentavano il tipo
- ho rimosso la firma di tipo
- ghci accettate la funzione
- Ho controllato il tipo dedotto
- il tipo dedotto era esattamente lo stesso del tipo che ho provato a dargli
- ero molto angosciato
- ho scoperto che avrei potuto riprodurre il problema in qualsiasi let-espressione
- stridore di denti; ha deciso di consultarsi con gli esperti di SO
tentativo di definire la funzione con una firma tipo:
Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x} :: (MonadPlus m) => (b -> Bool) -> m b -> m b
<interactive>:1:20:
Inferred type is less polymorphic than expected
Quantified type variable `b' is mentioned in the environment:
m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16)
f :: (m b -> m b) -> Bool (bound at <interactive>:1:14)
Quantified type variable `m' is mentioned in the environment:
m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16)
f :: (m b -> m b) -> Bool (bound at <interactive>:1:14)
In the expression:
do { x <- m;
guard (f x);
return x } ::
(MonadPlus m) => (b -> Bool) -> m b -> m b
In the definition of `myFilterM':
myFilterM f m
= do { x <- m;
guard (f x);
return x } ::
(MonadPlus m) => (b -> Bool) -> m b -> m b
Definita la funzione senza firma tipo, controllato il tipo derivato:
Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x}
Prelude Control.Monad> :t myFilterM
myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b
utilizzata la funzione per la gran bene - ha funzionato correttamente:
Prelude Control.Monad> myFilterM (>3) (Just 4)
Just 4
Prelude Control.Monad> myFilterM (>3) (Just 3)
Nothing
La mia ipotesi migliore da quello che sta succedendo:
annotazioni di tipo in qualche modo non funzionano bene con Let-espressioni , quando c'è un blocco.
per i punti bonus:
c'è una funzione nella distribuzione standard Haskell che fa questo? Sono stato sorpreso che lo filterM
faccia qualcosa di molto diverso.
L'annotazione del tipo si applica all'RHS della definizione, non a 'myFilterM', quindi dovresti dire' :: (MonadPlus m) => m b'. Questo è il motivo per cui i tipi di 'm' e' f' nel tuo messaggio di errore sono così strani. Ma ottengo ancora il messaggio di errore "Il tipo inferito è meno polimorfo del previsto" (anche se con tipi più sensibili) e non so che cosa lo causi. – dave4420
@ dave4420 Usi anche GHC 6. *? Hanno codificato un nuovo motore di inferenza di tipo in GHC 7; forse è un bug – fuz
@FUZxxl Questo era con GHC 6.12.1. Ho appena provato con GHC 7.0.3 e ricevo due messaggi di errore invece di uno, nessuno dei due menziona il polimorfismo. Potrebbe essere GHC 7 che rifiuta di dedurre i tipi di argomenti di 'myFilterM'. – dave4420