2015-11-29 5 views
2

J'essaie de lire un fichier dans une fonction pour calculer les fréquences de caractères dans un fichier. Donc, je suis en train de ce qui suit:Haskell readFile: Impossible de faire correspondre le type attendu '[String]' avec le type réel 'IO String'

charCount :: String -> [(Char, Int)] 
charCount input = M.toList $ M.fromListWith (+) [(c, 1) | c <- input] 

calculate :: FilePath -> [(Char, Int)] 
calculate fp = do 
    c <- readFile fp 
    charCount c 

Mais je reçois l'erreur suivante:

FileWriter.hs:13:8: Couldn't match expected type ‘[String]’ … 
       with actual type ‘IO String’ 
    In a stmt of a 'do' block: c <- readFile fp 
    In the expression: 
     do { c <- readFile fp; 
      charCount c } 
Compilation failed. 
+1

C'est un défaut du message d'erreur GHC. Le vrai problème est le suivant: 'calculate' ne peut pas renvoyer juste un type de liste (spécifiquement' [(Char, Int)] '). Vous lisez un fichier, ce qui signifie que vous avez "infecté" la fonction avec IO. La façon dont je pense à ce sujet est que toute fonction qui appelle une fonction IO devient alors une autre fonction IO. Essayez plutôt 'IO [(Char, Int)]' pour le type de retour. – hao

+0

Si je change le type de retour il est dit 'Impossible de correspondre au type attendu 'IO [(Char, Int)]' avec le type réel '[(Char, Int)]'' – astiefel

+0

Nous avons maintenant passé à des échecs de Haskell courbe d'apprentissage. Un indice: il existe une fonction avec le type 'a -> IO a', mais elle est déguisée en' (Monad m) => a -> m a'. – hao

Répondre

1

Depuis calculate appelle la fonction readFile qui retourne une valeur enveloppée dans la IO monade la fonction calculate doit retourner une IO valeur aussi, et le résultat de l'appel à charCount (un calcul pur) doit être return ed afin d'envelopper le [(Char, Int)] dans une monade.

L'exemple suivant travaillé dans ghc 7.10.1:

import qualified Data.Map as M 

charCount :: String -> [(Char, Int)] 
charCount input = M.toList $ M.fromListWith (+) [(c, 1) | c <- input] 

calculate :: FilePath -> IO [(Char, Int)] 
calculate fp = 
    readFile fp >>= \c -> 
    return (charCount c)