2012-02-08 4 views
0

Avec l'extrait ci-dessous, je souhaite ajouter/ajouter une chaîne à une liste faisant partie d'une valeur stockée dans une carte.Erreur de déclaration de type: [Char] et [[Char]]

A partir de l'extrait ci-dessous je reçois l'erreur

Couldn't match expected type `Char' with actual type `[Char]' 
    Expected type: Map.Map ([Char], Integer) [Char] 
     Actual type: Map.Map ([Char], Integer) [[Char]] 

et je ne suis pas tout à fait sûr de ce qui devrait me dire. Cela peut-il être résolu avec une modification du code ou doit-il y avoir quelque chose comme

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE FlexibleInstances #-} 

Avec une déclaration d'instance?

import Data.Time 
import Data.Time.Clock.POSIX 
import qualified Data.PSQueue as PSQ 
import qualified Data.Map as Map 
import Data.Maybe 
import Control.Category 
import Control.Concurrent 
import Control.Concurrent.MVar 
import Control.Monad 

key = ("192.168.1.1", 4711) 
messages = ["aaa", "bbbb", "ccccc"] 

newRq = do 
     time <- getPOSIXTime 
     let q = PSQ.singleton key time 
     let m = Map.singleton key messages 
     return (q, m) 

appendMsg :: String -> (String, Integer) -> Map.Map ([Char], Integer) [Char] -> Map.Map ([Char], Integer) [Char] 
appendMsg a (b, c) m = m2 
     where 
      f x = x ++ a 
      m2 = Map.adjust f (b, c) m 

main :: IO() 
main = do 
    (q, m) <- newRq 
    let m2 = appendMsg "first" key m 
    print (m2) 

Répondre

2

Vous avez besoin d'une modification dans le code. Vous commencez avec un Map (String, Integer) [String], en créant un singleton avec la valeur messages. Votre fonction de mise à jour est cependant écrite pour Map (String, Integer) String. Soit changer le type approprié en le rendant f x = x ++ [a] (et changer la signature de type à

appendMsg :: String -> (String, Integer) -> Map (String, Integer) [String] 
             -> Map (String, Integer) [String] 

aussi) ou modifier votre carte initiale en utilisant par exemple unwords messages. (Je pense que vous préférerez le premier.)

+0

Déjà essayé. Cependant, alors j'obtiens une erreur disant 'Aucune instance pour (IsString Char) découlant du littéral' 'ccccc" '. Ajouter 'import Data.String' n'aide pas non plus. –

+0

Oublié de mentionner, vous devez changer la déclaration de type 'appendMsg' pour utiliser' Map (String, Integer) [String] 'aussi. –

+0

Merci! Est-ce qu'un [String] n'est pas un [Char]? –

1

La carte que vous créez avec Map.singleton key messages est un Map.Map (String, Integer) [String]. Cependant, votre déclaration de appendMsg indique que vous voulez vraiment un Map.Map (String, Integer) String. Vous devez revoir votre newRq et comprendre ce que vous essayez vraiment de faire avec cette ligne Map.singleton.

2

[Char] et String sont du même type. Le prélude Haskell a la définition des synonymes de type:

type String = [Char] 

... ce qui signifie essentiellement ces deux types signifient exactement la même chose et sont complètement interchangeables. Cela signifie que nous pouvons réécrire l'erreur du compilateur comme:

Expected type: Map (String, Integer) String 
    Actual type: Map (String, Integer) [String] 

Les deux paramètres de type du type Map sont le type Key et son type Value. Donc, si vous avez un type Map Int String, cela signifie que c'est une carte avec Int s comme clés et Strings comme valeurs. Cela signifie que vous pouvez maintenant interpréter le message du compilateur un peu plus clair:

Expected type: Map from keys of type "(String, Integer)" to values of type "String" 
    Actual type: Map from keys of type "(String, Integer)" to values of type "[String]" 

Cela nous dit que quelque part dans votre code que vous avez donné une carte où chaque valeur est une [String] (ie une liste de chaînes), mais il attendait une carte où chaque valeur était juste un String. En fait, vous pouvez suivre l'erreur à cette ligne de code:

let m = Map.singleton key messages 

messages est, vous l'aurez deviné, une liste des String s (c.-à-[String]), et vous dit pour stocker tout le réseau messages comme élément unique dans la carte m lorsque vous avez utilisé la fonction singleton pour l'initialiser. Donc, Haskell a correctement déduit que le type de valeur m devait être [String] (ce qui n'était évidemment pas ce que vous vouliez).

Le compilateur a alors remarqué quelque chose clochait lorsque vous avez essayé d'ajouter une chaîne à chaque élément de votre carte dans la ligne suivante:

let m2 = appendMsg "first" key m 

Vous avez dit au compilateur « S'il vous plaît concaténer cette chaîne sur tous les éléments de mon map "et le compilateur vous dit" Mais vous n'avez pas plusieurs chaînes stockées dans votre map: vous n'avez qu'une seule liste de chaînes stockées en tant que valeur unique dans votre map, donc je ne peux pas ajouter 'first' sur le tableau lui-même ".

La solution est simple où au lieu d'utiliser singleton pour initialiser m, vous venez fromList, qui prend une liste d'éléments (c.-à-messages) et convertit chaque élément de la liste à un élément de la carte, qui est ce que vous vouliez .

+0

"(c'est-à-dire un tableau de chaînes)", je suppose que vous connaissez la différence et que vous étiez un peu sur vos gardes, mais il est important de garder la différence entre les listes et les tableaux pour éviter les débutants déroutants. Essayer de traiter les listes comme des tableaux est une erreur fréquente menant à la frustration. –

+0

Oui, je voulais dire la liste. –