3

当我被卡住时,我才刚刚开始玩 Haskell。

我正在尝试使我的新数据类型(我们称之为MyType)类的实例ReadMytype是一个类型构造函数,所以它需要另一个类型作为参数。我想写这种代码

    instance (Read a) => Read (MyType a) where
        readsPrec _ r = [foo (read r :: a ), r]

但它给了我以下错误

Could not deduce (Read a2) arising from a use of `read' from the context (Read a).

我认为既然 a isReadable我可以推断它,但显然我错了。有任何想法吗?

编辑: 我已将以前的代码更改为

readsPrec _ r = [foo (read r :: a ), ""]

所以如果我输入:read "myString" :: MyType a它工作得很好。现在我希望如果我read "myString"在上下文中使用,我不应该指定要读取的类型。但问题是

bar (read myString) a

其中bar:: MyType a -> a -> MyType a,我得到了 Ambiguos 变量类型

有没有可能做这样的事情而不会出现这种错误?

我希望现在更清楚了,我正在尝试简化代码,但我希望我没有遗漏任何重要的内容。

4

1 回答 1

6

如果写成,代码实际上会进行类型检查

实例 (Read a) => Read (MyType a) 其中
        readsPrec _ r = [(foo (读取 r),r)]

如果foo有类型a -> MyType areadsPrec编译器可以从调用的预期类型签名中找出foo应该返回 a MyType a,因此(根据 的类型foo),表达式read r应该有 type a

但是为什么当你用 注释它时它会失败:: a?因为类型变量对于它们出现的类型签名来说是本地的。所以与实例头中的a完全无关,并且您实际上是在说:表达式可以具有任意类型。但是任意类型没有实例,因此出现错误消息。在消息中,编译器重命名了内部以避免名称冲突。aread r :: aread rReadaa2

但是,如果您添加{-# LANGUAGE ScopedTypeVariables #-}到模块标头,您的代码可以按预期工作。现在,ainread r :: a指的a是实例标头中的类型,一切顺利。

请注意,您没有正确使用 readsPrec,但我想这不是问题的一部分。

于 2012-11-23T09:01:11.850 回答