假设我有这样的数据类型:
{-# LANGUAGE RankNTypes #-}
data X a = forall b. Show b => X (a b)
我想导出Show (X a)
,但当然我只能在有实例的情况下这样做Show (a b)
。我很想写
{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show (a b) => Show (X a)
但不幸的是类型变量b
在实例上下文中不可用,因为它受 forall 绑定。
我的下一个尝试是移动Show (a b)
将上下文放入数据类型定义中的 forall 中,如下所示:
data X a = forall b. Show (a b) => X (a b)
deriving instance Show (X a)
这可以编译,但不幸的是现在我已经失去了构建X
带着无法表现的(a b)
.
有什么办法可以允许X
可以用任何构造(a b)
,然后有条件地导出Show (X a)
除非(a b)
是可以展示的吗?
这是前奏课的一个不足。有一个很好的解决方法,尽管体现在prelude-extras http://hackage.haskell.org/package/prelude-extras包裹。我将在下面概述它。
我们想创造一个更高级的Show
班级。看起来像这样
class Show1 a where
show1 :: Show b => a b -> String
那么我们至少可以准确地表达我们想要的约束,例如
deriving instance Show1 a => Show (X a)
不幸的是,编译器还没有足够的信息来实现这一推导。我们需要证明(Show b, Show1 a)
足以得出Show (a b)
。为此,我们需要启用一些(可怕但正常使用的)扩展
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
instance (Show b, Show1 a) => Show (a b) where
show = show1
现在我们有了证据,编译器将能够导出我们需要的东西
data X a = forall b . Show b => X (a b)
deriving instance Show1 a => Show (X a)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)