2012-06-26 8 views
1

Je vous écris un enregistreur pour une fonction de tri comme ceci:Haskell Monad.Writer

bubble :: (Ord a) => [a] -> Writer [String] [a] 
bubble (x:y:ys) 
     | x > y = do 
       tell [show x ++ " why does this not work"] 
       y:bubble(x:ys) 
     | otherwise = do 
       tell [show y ++ " is a number"] 
       x:bubble(y:ys) 
bubble [x] = do 
      tell ["nothing works"] 
      return [x] 

mais je reçois cette erreur:

Couldn't match expected type `WriterT 
            [String] Data.Functor.Identity.Identity [a]' 
       with actual type `[a0]' 
    In a stmt of a 'do' block: y : bubble (x : ys) 
    In the expression: 
     do { tell [show x ++ " why does this not work"]; 
      y : bubble (x : ys) } 
    In an equation for `bubble': 
     bubble (x : y : ys) 
      | x > y 
      = do { tell [show x ++ " why does this not work"]; 
       y : bubble (x : ys) } 
      | otherwise 
      = do { tell [show y ++ " is a number"]; 
       x : bubble (y : ys) } 
Failed, modules loaded: none. 

J'ai lu ce message d'erreur mot pour mot, mais je je ne suis pas plus proche de quel est le problème? J'ai essayé de compiler avec la décélération, pour une nouvelle série d'erreurs comme ceci:

q.hs:21:17: 
    No instance for (MonadWriter [[Char]] []) 
     arising from a use of `tell' 
    Possible fix: 
     add an instance declaration for (MonadWriter [[Char]] []) 
    In a stmt of a 'do' block: 
     tell [show x ++ " why does this not work"] 
    In the expression: 
     do { tell [show x ++ " why does this not work"]; 
      y : bubble (x : ys) } 
    In an equation for `bubble': 
     bubble (x : y : ys) 
      | x > y 
      = do { tell [show x ++ " why does this not work"]; 
       y : bubble (x : ys) } 
      | otherwise 
      = do { tell [show y ++ " is a number"]; 
       x : bubble (y : ys) } 
Failed, modules loaded: none. 

Répondre

3

Un clin d'œil à droite:

  1. Quel est le type de y? Quel est le type de bubble(x:ys)? Quel est le type de (:)?

Réponses:

(Dans ces réponses, a est le même que dans abubble :: (Ord a) => [a] -> Writer [String] [a].)

  1. y :: a
  2. bubble(x:ys) :: Writer [String] [a]
    • bubble est une fonction, bubble(x:ys) est le résultat de l'application de bubblex:ys
  3. (:) :: b -> [b] -> [b]
    • : est un opérateur; quel que soit le type de son premier opérande, son deuxième opérande doit avoir le type "liste de tout type du premier opérande", et le résultat a le même type de liste.

Étant donné que vous avez donné y et bubble(x:ys) comme opérandes à :, pouvez-vous voir maintenant quel est le problème?

+0

hmm est 1. Ord a 2. une fonction appelée avec une liste 3. l'opérande pour ajouter un élément à une liste? Dois-je changer mes déclarations? –

+1

Non, votre déclaration me semble bonne. plus :) – mergeconflict

+0

@baronaron Votre déclaration de type est correcte, le problème est dans la ligne 'y: bubble (x: ys)'. Voir mon edit – dave4420

3

Il est quelque peu regrettable, dans ce cas, que Writer w a soit un synonyme de WriterT w Identity a. Cela rend les messages d'erreur du compilateur (qui sont normalement très instructifs) beaucoup plus difficiles à interpréter. Donc, ma suggestion ici est simplement ignorer le contenu du message d'erreur entièrement et prétendre que vous êtes le vérificateur de type.

@ dave4420 fourni un très bon indice, je pense. Je vais ajouter à cela en disant: ne pas supprimer la déclaration de type pour bubble - à la place, aller dans le sens inverse: casser bubble en plus petites fonctions d'aide, fournissant des déclarations de type pour chacun. Ensuite, il devrait devenir beaucoup plus clair où se situe votre problème. Mon seul autre indice est qu'il s'agit d'un problème courant lors de l'écriture d'un code monadique: se souvenir quelles valeurs sont de type monadique, lesquelles ne le sont pas, et quand "lever"."