代码之家  ›  专栏  ›  技术社区  ›  gspr

使用常量值退化typeclass实例声明

  •  4
  • gspr  · 技术社区  · 15 年前

    我已经把所有的东西都简化到了最基本的部分,所以如果下面的示例代码是人为的,请耐心等待。假设我们有:

    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 表演 ( 表演 被选择以避免定义另一个类型类)。那我们想要什么 A型 成为 表演 ?好吧,除非我们疯了,我们当然想让它像

    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”[…]“show 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 回复  |  直到 15 年前
        1
  •  6
  •   luqui    15 年前

    认为 问题是类型变量的作用域不属于定义。也就是说,在

    instance (Foo a, Show a) => Show (Type a) where
        show _ = show (foo :: 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)
    
    推荐文章