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

gsp*_*spr 4 haskell typeclass

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

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)

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

Ale*_*nov 6

认为问题是类型变量没有作用于定义.也就是说,在

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)

  • 好的答案除了导致非终止的小错字:最后一行应该是`show(Type x)= show(foo \`asTypeOf \`x)`.你也可以使用`{ - #LANGUAGE ScopedTypeVariables# - }`和`show _ = show(foo :: a)` (5认同)
  • Alexey:至少我不需要“forall”。在我的示例中,我打开了 GHC 扩展并将 `show` 实现为 `show _ = show (foo :: a)`。它工作得很好。很高兴了解您的 `asTypeOf` 方法。 (2认同)