使用下面的代码片段,我想将一个字符串附加/前置一个列表,该列表是存储在地图中的值的一部分。
从下面的代码段我得到错误
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)
答案 0 :(得分: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
。 (我想你宁愿第一个。)
答案 1 :(得分:2)
[Char]
和String是相同的类型。 Haskell前奏具有以下类型的同义词定义:
type String = [Char]
...这基本上意味着这两种类型意味着完全相同的东西,并且完全可以互换。这意味着我们可以将编译器错误重写为:
Expected type: Map (String, Integer) String
Actual type: Map (String, Integer) [String]
Map
类型的两个类型参数是其Key
类型及其Value
类型。因此,如果您使用Map Int String
类型,则表示这是一张地图,其中Int
为密钥,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
存储为单个元素在使用m
函数初始化它时,在地图singleton
中。所以Haskell正确地推断出m
的值类型必须是[String]
(这显然不是你想要的)。
当您尝试将字符串附加到地图中以下行中的每个元素时,编译器会注意到有些不对劲:
let m2 = appendMsg "first" key m
你告诉编译器“请将这个字符串连接到我的地图的每个元素上”然后编译器会告诉你“但你没有在你的地图中存储多个字符串;你只有一个字符串列表存储为一个你的地图中的值,所以我不能将'first'追加到数组本身“。
修复很简单,而不是使用singleton
初始化m
,而只需fromList
,它会获取元素列表(即messages
)并转换每个元素在列表中的一个元素,这是你想要的。
答案 2 :(得分:1)
您使用Map.singleton key messages
创建的地图是Map.Map (String, Integer) [String]
。但是,您appendMsg
的声明表明您确实需要Map.Map (String, Integer) String
。您需要重新访问newRq
并找出您真正尝试使用Map.singleton
行的内容。