2017-04-06 2 views
2

Je suis juste jouer avec Haskell monades et je continue à obtenir une erreur que je ne peux pas sembler corriger. Mon segment de code utilise l'état Monad pour ajouter les deux premiers caractères d'une chaîne ensemble et les renvoyer dans le cadre de l'état. Ma ligne "put" continue à me donner l'erreur:continue à recevoir (Utilisez FlexibleContexts pour permettre cette) Erreur dans la fonction simple Haskell

* Non type-variable argument in the constraint: MonadState [a] m 
    (Use FlexibleContexts to permit this) 
* When checking the inferred type 
    testH :: forall (m :: * -> *) a. MonadState [a] m => [a] -> m [a] 

Comment puis-je résoudre ce problème? L'extension de la langue n'est pas une option, je veux juste savoir comment je peux changer mon code pour faire fonctionner

test xs = 
runState (testH (tail xs)) ((head xs):[]) 

testH xs = 
do 
    a <- get 
    put ((head xs):a) 
    b <- get 
    return b 
+0

Importez-vous 'Control.Monad.State'? Si c'est le cas, essayez plutôt d'importer 'Control.Monad.Trans.State'. – Alec

+1

Je ne suis pas entièrement sûr de savoir ce que vous entendez par "L'extension de la langue n'est pas une option". Si vous ne faites que jouer avec des monades, pourquoi ne pas ajouter '{- # LANGUAGE FlexibleContexts # -}' en haut de votre code? – Lazersmoke

+0

"L'extension de la langue n'est pas une option", sauf que vous utilisez 'MultiParamTypeClasses' simplement en ayant MonadState' dans la portée et que vous avez donc déjà étendu la langue. –

Répondre

0

Vous pouvez résoudre cela soit en permettant FlexibleContexts comme il le suggère, ou en changeant votre fonction de travailler sur quelque chose de plus général que les listes.

Le problème est que Haskell n'autorise pas les variables non-typées dans un contexte. Si vous écrivez les types de vos fonctions (que vous devriez faire de toute façon), vous obtenez

testH :: (Monad m,MonadState [a] m) => [a] -> m [a] 

qui signifie qu'il est une fonction qui prend une liste de valeurs et retourne une action dans certains monade qui a la capacité conserver un état d'une liste de valeurs du même type que l'entrée. Malheureusement, le bit [a] dans le contexte n'est pas valide Haskell car il a une variable non-type chose (à savoir le constructeur de type liste).

La meilleure solution ici est simplement d'activer l'extension, ce qui permet choses variables de type non dans les contextes. Ce n'est pas dangereux, ça détend juste la norme. En fait, les typeclasses multi-paramètres (tels que MonadState) ne sont pas des Haskell valides, donc vous utilisez déjà des extensions de langue que vous le vouliez ou non.

Si ce n'est vraiment pas une option, vous pouvez le changer en (Monad m,SomeTypeclass f,MonadState (f a) m), et réécrire vos fonctions pour travailler avec n'importe quel constructeur qui suit le SomeTypeclass de votre choix. Cela supprime le constructeur de type liste du type et permet au code de fonctionner sans FlexibleContexts.