我已将所有内容减少到必需品,所以如果下面的示例代码是设计的,请耐心等待。假设我们有:
class Foo a where
foo :: a
data Type a = Type a
instance (Foo a) => Foo (Type a) where
foo = Type foo
现在,我想假设Type a
是Show
的实例,只要a
是Foo
和Show
的实例Show
选择{1}}以避免定义另一个类型类)。那么我们如何让Type a
成为Show
的实例?好吧,除非我们疯了,否则我们当然希望它像
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = show x
或者
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = "Blabla " ++ (show x)
这一切都很棒并且工作正常。出于某种莫名其妙的原因,我们希望show
输出foo :: a
看起来/显示的内容!在我们设计的环境中,我无法想象为什么我们想要那样,但让我们说我们做到了。不应该
instance (Foo a, Show a) => Show (Type a) where
show _ = show foo
诀窍?
唉,GHC说
不明确的类型变量'a' 约束:'Foo a'[...]'显示'
也许GHC无法弄清楚我在说什么foo
。我的意思是foo :: Type a
还是foo :: a
?将上一个代码段更改为
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
给了我
无法从中推断(Foo a1) 上下文() 在[...]使用'foo'引起的 可能的修复: 将(Foo a1)添加到表达式类型签名的上下文中 在'show'的第一个参数中,即'(foo :: a)' 在表达式中:show(foo :: a)
此时我开始认为我误解了一些基本的东西。然而,我有一种奇怪的感觉,过去类似的结构对我有用。
答案 0 :(得分:6)
我认为问题是类型变量没有作用于定义范围。也就是说,
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
第二行中的 a
与第一行中的a
不同,这就是错误消息中显示为a1
的原因。见http://www.haskell.org/haskellwiki/Scoped_type_variables。如果这是问题,这应该工作(我在这台机器上没有GHC):
asTypeOf :: a -> a -> a
asTypeOf a b = a
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = show (foo `asTypeOf` x)