【问题标题】:Haskell Couldn't Match Expected TypesHaskell 无法匹配预期的类型
【发布时间】:2012-08-14 01:54:00
【问题描述】:

所以,我已经用头撞墙至少一个小时了。这是我的问题:

我的一个函数返回[(Text, Text)]

现在我想使用这个元组列表在 Data.Bson 中填充 Document。

打开扩展名OverloadedStrings,并导入Data.Text 以及Data.Bson,我会这样做(这部分是从原始帖子编辑的,我粘贴了实际上没有的代码的调试版本使用累加器):

tuplesToBSON :: [(Text, Text)] -> Document
tuplesToBSON xs = L.foldr (\v acc -> merge [fst v =: snd v] acc) [] xs 

merge 来自 Data.Bson 包,=: 也是如此。

运气不好。它抱怨:无法将预期类型 Label 与实际类型 Text 匹配。 (为了清楚起见,下面也是一个编辑)如果我尝试:

tuplesToBSON xs = L.foldr (\v acc -> merge [(fst v) =: (String (snd v))] acc ) [] xs

不幸的是,这个名为 String 的构造函数实际上是来自 Bson 包的构造函数(我认为......),用于名为“Value”的数据类型。 http://hackage.haskell.org/packages/archive/bson/0.2.1/doc/html/src/Data-Bson.html

这仍然不起作用-但出现不同的错误消息:

No instance for (Val Value) arising from a use of `=:'
Possible fix: add an instance declaration for (Val Value)
In the expression: (fst v) =: (String (snd v))
In the first argument of `merge', namely `[(fst v) =: (String (snd v))]'
In the expression: merge [(fst v) =: (String (snd v))] acc

还有:

Couldn't match expected type `Label' with actual type `Text'
Expected type: [(Label, text-0.11.2.0:Data.Text.Internal.Text)] Actual type: [(Text, Text)]
In the third argument of `L.foldr', namely `xs'
In the expression: L.foldr (\ v acc -> merge [(fst v) =: (String (snd v))] acc) [] xs

我知道 Value 是 Bson 包中的一种数据类型,但我真的不知道 Val 是什么。

===== 不相关部分的开始 =====

正如下面的答案之一指出的那样,在原始帖子中,我的代码中有:: StringText“转换”为String,就像在前奏中一样。我实际上以为:: String 指的是Bson 包中提到的那个,但无论如何我完全错了,因为(我认为)String 实际上是一个构造函数。

我怀疑 GHC 类型推断在某种程度上被混淆了,因为以下工作正常:

testDocument :: Document
testDocument = [(fst ("asdf", "awef") :: Label) =: ("asdf" :: String)]

编辑:这可行,但必须是因为 Bson 自动进行了一些正确的类型处理,因为在包含 import Prelude hiding (String) 行之后,它给了我一个错误。

所以我终于解决了这个问题。对不起之前的混乱版本——我很沮丧。

【问题讨论】:

  • 顺便说一句,您正在将acc 丢在地板上。也许您打算使用 ((fst v) := (snd v)) : acc 而不是只返回一个 1 元素列表?
  • 哦,是的,那实际上还是调试代码 :)

标签: haskell


【解决方案1】:

我认为您的问题不是Label,而是b0。看起来您正试图断言 snd vString 而不是。尝试使用类似的东西

tuplesToBSON xs = L.foldr (\acc v ->  [ ((fst v) :: Label) := (unpack (snd v) :: String)] ) [] xs

虽然我不太确定所有内联类型断言的用途。这可能更具可读性

tuplesToBSON xs = L.foldr (\acc v -> [(fst v) := (unpack (snd v0)]) [] xs

【讨论】:

  • 感谢您的回复。让我编辑我的帖子,因为我忘记了我应该包含更合适的涉及 foldr 的代码行。编辑:实际上忘记了原始的编辑,我现在对问题有了更好的了解,我将追加编辑。
  • 感谢您对字符串部分的评论——我并没有完全考虑 Prelude.String,但我确实混淆了 Bson 的值数据的字符串构造函数。现在更近了;还是有问题!
  • @Victor:您更新后的代码使用了=:,但Data.Bson 运算符似乎是:=
  • 哦,我明白了。但我不明白 := 定义——什么是“!”在“!标签”中?
  • @Victor:它在数据定义中引入了严格性。基本上,它可以防止该字段被装箱。
【解决方案2】:

首先,不清楚您要做什么。你甚至没有使用累加器 (acc) 所以这是一个退化的遍历。你不妨说:

tuplesToBSON = (\v -> fst v =: snd v) . last

另一个问题是你的类型显然是矛盾的。你说你传入一个Text,然后在你明确声明你认为变量应该是String的lambda中。正如您在问题中所说,您不能只添加类型注释并将它们视为强制操作。变量的类型必须保持一致,并且任何强制都由显式函数应用程序完成(在这种情况下为unpack)。

所以让我们假设这只是对 foldr 的错误使用,我们想要实际使用累加器。让我们进一步假设您想要Text 类型,而任何String 的使用都是偶然的。

第三个问题是您似乎混淆了变量,在foldr 中,第二个参数是累加器,而不是第一个。所以我们应该有:

tuplesToBSON = foldr (\v acc -> (fst v =: snd v) : acc) []

而且这种类型检查良好。如果 eta 减少和其他清理让您很难看到与您的代码的相似性,那么考虑这个版本:

tuplesToBSON xs = foldr (\v acc -> ((fst v :: Label) =: (snd v :: Text)) : acc ) [] xs

【讨论】:

  • 对不起,我实际上粘贴了调试代码,而我要粘贴的是实际使用累加器的东西......不过,让我先试试你的建议。感谢您的回复。
  • 感谢您对变量 foldr (\v acc) 顺序的评论。我需要很长时间才能弄清楚这一点。
猜你喜欢
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 2020-09-05
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多