首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型声明错误:[Char]和[[Char]]

类型声明错误:[Char]和[[Char]]
EN

Stack Overflow用户
提问于 2012-02-09 07:27:26
回答 3查看 256关注 0票数 0

使用下面的代码片段,我希望将一个字符串附加/预先添加到一个列表中,该列表是存储在映射中的值的一部分。

从下面的代码片段中,我得到了错误

代码语言:javascript
复制
Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: Map.Map ([Char], Integer) [Char]
      Actual type: Map.Map ([Char], Integer) [[Char]]

我不太确定这应该告诉我什么。可以通过更改代码来解决这个问题吗?或者必须有如下内容

代码语言:javascript
复制
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}

与实例声明一起使用?

代码语言:javascript
复制
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)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-09 07:32:38

您需要在代码中进行更改。首先创建一个值为messages的单例( Map (String, Integer) [String] )。但是,您的更新函数是为Map (String, Integer) String编写的。通过将其设置为f x = x ++ [a]将其更改为适当的类型(并将类型签名更改为

代码语言:javascript
复制
appendMsg :: String -> (String, Integer) -> Map (String, Integer) [String]
                                         -> Map (String, Integer) [String]

也可以),或者通过使用unwords messages来更改初始地图。(我想您会更想要第一个。)

票数 2
EN

Stack Overflow用户

发布于 2012-02-09 13:50:29

[Char]和String是同一类型。Haskell前奏具有以下类型同义词定义:

代码语言:javascript
复制
type String = [Char]

..。这基本上意味着这两种类型的含义是完全相同的,并且完全可以互换。这意味着我们可以将编译器错误重写为:

代码语言:javascript
复制
Expected type: Map (String, Integer) String
  Actual type: Map (String, Integer) [String]

Map类型的两个类型参数是它的Key类型和Value类型。因此,如果你有一个Map Int String类型,这意味着它是一个以Ints作为键,Strings作为值的映射。这意味着您现在可以更清楚地解释编译器消息:

代码语言:javascript
复制
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的映射。实际上,您可以将错误追溯到下面这行代码:

代码语言:javascript
复制
let m = Map.singleton key messages

您已经猜到了,messagesString的列表(即[String]),当您使用singleton函数初始化它时,您告诉它将整个数组messages作为单个元素存储在映射m中。因此,Haskell正确地推断出m的值类型一定是[String] (这显然不是您想要的)。

然后,编译器注意到当您尝试将字符串附加到映射中的以下行中的每个元素时,出现了问题:

代码语言:javascript
复制
let m2 = appendMsg "first" key m

您告诉编译器“请将此字符串连接到我的map的每个元素上”,然后编译器告诉您“但是您的map中没有存储多个字符串;您的map中只有一个字符串列表作为单个值存储,所以我不能将'first‘附加到数组本身”。

修复方法很简单,不是使用singleton来初始化m,而是使用fromList,它接受一个元素列表(即messages),并将列表中的每个元素转换为映射的一个元素,这正是您想要的。

票数 2
EN

Stack Overflow用户

发布于 2012-02-09 07:32:49

您使用Map.singleton key messages创建的地图是一个Map.Map (String, Integer) [String]。但是,您对appendMsg的声明表明您确实需要一个Map.Map (String, Integer) String。您需要重新访问您的newRq,并弄清楚您真正想要用该Map.singleton行做什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9203171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档