Haskell 使用常量值的退化typeclass实例声明
我已经将所有内容简化为基本内容,如果下面的示例代码是人为设计的,请耐心等待。假设我们有:Haskell 使用常量值的退化typeclass实例声明,haskell,typeclass,Haskell,Typeclass,我已经将所有内容简化为基本内容,如果下面的示例代码是人为设计的,请耐心等待。假设我们有: 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是为了避免定义另一个typeclass)。那么我们希望类型a如何成为Show的实例呢?
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
是为了避免定义另一个typeclass)。那么我们希望类型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”[…]”显示a'
也许GHC搞不清我说的是哪个foo
。我是说foo::Type a
还是foo::a
?将上一个代码段更改为
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
给我
无法从
上下文()
因在[…]使用“foo”而产生
可能的解决方案:
将(fooa1)添加到表达式类型签名的上下文中
在'show'的第一个参数中,即'(foo::a)'
在表达式中:show(foo::a)
在这一点上,我开始认为我误解了一些基本的东西。然而,我有一种奇怪的感觉,类似的构造在过去对我起了作用。我认为问题在于类型变量的作用域并不局限于定义。就是在
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
第二行中的a
与第一行中的a
不同,这就是为什么它在错误消息中显示为a1
。看见如果这是问题所在,这应该可以工作(我在这台机器上没有GHC):
回答很好,除了一个导致不终止的小错误:最后一行应该是
show(Type x)=show(foo`asTypeOf`x)
。您还可以使用{-#语言范围的TypeVariables}
以及show=show(foo::a)
太棒了!谢谢,这真的澄清了问题。还要感谢pelotom指出了GHC扩展。我之所以没有提到该扩展,是因为它需要明确地编写forall
,但我不确定它应该去哪里:instance forall a。(Foo a,Show a)=>Show(Type a)
?其他地方?实例不需要?Alexey:至少我不需要所有的。在我的示例中,我打开了GHC扩展,并将show
实现为show.=show(foo::a)
。它工作得很好。很高兴知道你的asTypeOf
方法。“我不需要至少所有的。”很高兴知道!
asTypeOf :: a -> a -> a
asTypeOf a b = a
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = show (foo `asTypeOf` x)