使用常量值退化类型类实例声明

时间:2010-10-28 08:36:59

标签: haskell typeclass

我已将所有内容减少到必需品,所以如果下面的示例代码是设计的,请耐心等待。假设我们有:

class Foo a where
    foo :: a

data Type a = Type a

instance (Foo a) => Foo (Type a) where
    foo = Type foo

现在,我想假设Type aShow的实例,只要aFooShow的实例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)

此时我开始认为我误解了一些基本的东西。然而,我有一种奇怪的感觉,过去类似的结构对我有用。

1 个答案:

答案 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)