简体   繁体   English

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

[英]Degenerate typeclass instance declaration using constant value

I've reduced everything down to the essentials, so bear with me if the example code below is contrived. 我已将所有内容减少到必需品,所以如果下面的示例代码是设计的,请耐心等待。 Let's say we have: 假设我们有:

class Foo a where
    foo :: a

data Type a = Type a

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

Now, suppose I want to make Type a an instance of, say, Show whenever a is an instance of both Foo and Show ( Show was chosen to avoid defining another typeclass). 现在,假设我想让Type a一个实例,比如Show只要aFooShow的实例(选择Show是为了避免定义另一个类型类)。 So how do we want Type a to be an instance of Show ? 那么我们怎么想让Type a成为Show一个实例呢? Well, unless we're crazy, we'd of course want it to be something like 好吧,除非我们疯了,否则我们当然希望它是这样的

instance (Foo a, Show a) => Show (Type a) where
    show (Type x) = show x

or maybe 或者可能

instance (Foo a, Show a) => Show (Type a) where
    show (Type x) = "Blabla " ++ (show x)

That's all great and works fine. 这一切都很好,工作正常。 For some inexplicable reason, we'd like show to output whatever foo :: a looks/shows like! 出于某种莫名其妙的原因,我们希望show输出foo :: a look / shows之类的东西! In our contrived setting I cannot imagine why we'd want that, but let's say we do. 在我们设计的环境中,我无法想象为什么我们想要那样,但让我们说我们做到了。 Shouldn't 不能

instance (Foo a, Show a) => Show (Type a) where
    show _ = show foo

do the trick? 做诀窍?

Alas, GHC says 唉,GHC说

Ambiguous type variable 'a' in the constraints: 'Foo a' [...] 'Show a' 约束中的模糊类型变量'a':'Foo a'[...]'显示'

Maybe GHC can't figure out which foo I'm talking about. 也许GHC想不通这foo我在说什么。 Do I mean foo :: Type a or foo :: a ? 我的意思是foo :: Type afoo :: a Changing the previous snippet to 将上一个代码段更改为

instance (Foo a, Show a) => Show (Type a) where
    show _ = show (foo :: a)

gives me 给我

Could not deduce (Foo a1) from the context () arising from a use of 'foo' at [...] Possible fix: add (Foo a1) to the context of an expression type signature In the first argument of 'show', namely '(foo :: a)' In the expression: show (foo :: a) 无法推断(Foo a1)来自于[...]使用'foo'引起的context()可能的修复:将(Foo a1)添加到表达式类型签名的上下文中在'show'的第一个参数中,即'(foo :: a)'在表达式中:show(foo :: a)

At this point I'm starting to think I've misunderstood something basic. 在这一点上,我开始认为我误解了一些基本的东西。 Yet, I have the strange feeling that similar constructions have worked for me in the past. 然而,我有一种奇怪的感觉,过去类似的结构对我有用。

I think the problem is that type variables aren't scoped to definitions. 认为问题是类型变量没有作用于定义。 That is, in 也就是说,在

instance (Foo a, Show a) => Show (Type a) where
    show _ = show (foo :: a)

a in the second line is different from a in the first line, which is why it's shown as a1 in the error message. a在第二行不同于a在第一行,这就是为什么它示为a1中的错误消息。 See http://www.haskell.org/haskellwiki/Scoped_type_variables . 请参见http://www.haskell.org/haskellwiki/Scoped_type_variables If this is the problem, this should work (I don't have GHC on this machine): 如果这是问题,这应该工作(我在这台机器上没有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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM