我已将所有内容减少到必需品,所以如果下面的示例代码是设计的,请耐心等待.假设我们有:
class Foo a where
foo :: a
data Type a = Type a
instance (Foo a) => Foo (Type a) where
foo = Type foo
Run Code Online (Sandbox Code Playgroud)
现在,假设我想创建Type a一个实例,比如,Show 每当a两个实例都是(Foo并且被选择以避免定义另一个类型类).那么我们如何成为一个实例呢?好吧,除非我们疯了,否则我们当然希望它是这样的ShowShowType aShow
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = show x
Run Code Online (Sandbox Code Playgroud)
或者可能
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = "Blabla " ++ (show x)
Run Code Online (Sandbox Code Playgroud)
这一切都很好,工作正常.出于某种莫名其妙的原因,我们想show输出任何foo :: a外观/节目!在我们设计的环境中,我无法想象为什么我们想要那样,但让我们说我们做到了.不能
instance (Foo a, Show a) => Show (Type a) where
show _ = show foo
Run Code Online (Sandbox Code Playgroud)
做诀窍?
唉,GHC说
约束中的模糊类型变量'a':'Foo a'[...]'显示'
也许GHC无法弄清楚foo我在说什么.我是说foo :: Type a还是foo :: a?将上一个代码段更改为
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
Run Code Online (Sandbox Code Playgroud)
给我
无法推断(Foo a1)来自于[...]使用'foo'引起的context()可能的修复:将(Foo a1)添加到表达式类型签名的上下文中在'show'的第一个参数中,即'(foo :: a)'在表达式中:show(foo :: a)
在这一点上,我开始认为我误解了一些基本的东西.然而,我有一种奇怪的感觉,过去类似的结构对我有用.
我认为问题是类型变量没有作用于定义.也就是说,在
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)