2012-02-08 116 views
0

下面的代码片段中,我想将一个字符串附加到/ prepend一个字符串作为存储在地图中的值的一部分。类型声明错误:[Char]和[[Char]]

从片段下方出现错误

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

,我不太清楚什么应该告诉我。能与代码的改变来解决,或者必须有什么样

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE FlexibleInstances #-} 
与实例声明

在一起吗?

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) 

回答

2

您需要更改代码。您从Map (String, Integer) [String]开始,创建一个值为messages的单身人士。但是,您的更新功能是为Map (String, Integer) String编写的。或者通过使它f x = x ++ [a]其更改为适当的类型(和改变型签名

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

太)或通过使用例如改变您的初始地图unwords messages。 (我认为你宁愿要第一个。)

+0

已经试过了。然而,然后我得到一个错误,说'没有实例(IsString Char) 从字面上''ccccc''产生。添加'import Data.String'也没有帮助。 – 2012-02-09 10:16:56

+0

忘了提及,你必须改变'appendMsg'的类型声明以使用'Map(String,Integer)[String]'。 – 2012-02-09 10:25:17

+0

谢谢!顺便说一下[String]不是[Char]? – 2012-02-09 10:56:54

1

你用Map.singleton key messages创建的地图是Map.Map (String, Integer) [String]。但是,您的appendMsg声明表示您确实需要Map.Map (String, Integer) String。您需要重新访问您的newRq,并找出您真的想用Map.singleton这条线做什么。

2

[Char]和String是相同的类型。哈斯克尔序幕具有以下类型同义词定义:

type String = [Char] 

...这基本上意味着这两种类型的意思是完全一样的事情,是完全可以互换的。这意味着我们可以重写编译器错误如:

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

Map型两个类型参数是其Key类型及其Value类型。所以,如果你有一个Map Int String类型,这意味着它是一个Int s作为键和Strings作为值的地图。这意味着您现在可以解释稍微清楚编译器消息:

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]" 

这就告诉我们,在你的代码的某个地方,你给它一个地图,每一个值是[String](即的字符串名单)但它期望一张地图,其中每个值都只是一个String。事实上,你可以跟踪误差这行代码:

let m = Map.singleton key messages 

messages是,你猜对了,的String S(即[String])的列表,你告诉它整个阵列messages存储为当您使用singleton函数对其进行初始化时,地图中的单个元素为m。所以哈斯克尔正确推断m的值类型必须是[String](这显然不是你想要的)。

然后,编译器发现有些不对劲,当你试图追加一个字符串的每个元素在地图下面一行:

let m2 = appendMsg "first" key m 

你告诉编译器“请串连这个字符串到的每一个元素我地图“,然后编译器会告诉你”但是你的地图中没有多个字符串存储;在地图中只有一个字符串列表存储为单个值,所以我不能将'first'追加到数组上本身”。

解决方法是简单的,而不是使用singleton哪里初始化m,你只是fromList,这需要的元素(即messages)的列表,把每个元素列表中的地图,的元素是你的原意。

+0

“(即一串字符串)”,我想你知道它们的区别,只是有点不值得,但保持列表和数组之间的区别很重要,以避免混淆新手。试图将列表视为数组是导致沮丧的常见错误。 – 2012-02-09 10:02:36

+0

是的,我打算说清单。 – 2012-02-09 15:30:16

相关问题