问题描述
假设我有这样的数据类型:
$ $ p $ $ $ $ $ $ $ $ $ b $ { a = forall b。显示b => X(ab)
我想派生 Show(X a)
,但我当然只能在 Show(ab)
的实例中这样做。我很想写
{ - #LANGUAGE StandaloneDeriving# - }
导出实例Show(ab)=> ;显示(X a)
但不幸的是,类型变量 我的下一个尝试是将 b $ c
上下文到数据类型定义中的所有内容中,如下所示:
Show(ab)移动到实例上下文中,因为它受到全部绑定。
data X a = forall b 。 Show(a b)=> X(ab)
导出实例Show(X a)
我失去了用一个难以显示的(ab)
构造 X
的能力。
有没有办法允许 X
用任何(ab)
构造,然后仅当(ab)
可显示时有条件地派生 Show(X a)
?
这是Prelude类的一个缺陷。尽管体现在 prelude-extras
一个>包。我将在下面概述它。
我们希望创建一个更高级的 Show
类。它看起来像这样
class Show1 a where
show1 :: Show b => a b - >字符串
然后我们至少可以准确地表达我们想要的约束,例如
派生实例Show1 a =>显示(X a)
不幸的是,编译器还没有足够的信息来实现这个派生。我们需要证明(Show b,Show1 a)
足以导出 Show(a b)
。为了做到这一点,我们需要启用一些(可怕的,但是非常有用的)扩展
{ - #LANGUAGE FlexibleInstances# }
{ - #LANGUAGE OverlappingInstances# - }
instance(Show b,Show1 a)=>显示(ab)其中
show = show1
现在我们已经证明了编译器将能够推导出我们需要的数据。b b
data X a = forall b。显示b => X(a b)
导出实例Show1 a =>显示(X a)
Suppose I have a data type like this:
{-# LANGUAGE RankNTypes #-}
data X a = forall b. Show b => X (a b)
I would like to derive Show (X a)
, but of course I can only do so if there is an instance of Show (a b)
. I'm tempted to write
{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show (a b) => Show (X a)
but unfortunately the type variable b
is not available in the instance context because it is bound by the forall.
My next attempt was to move the Show (a b)
context into the forall in the data type definition, like so:
data X a = forall b. Show (a b) => X (a b)
deriving instance Show (X a)
This compiles, but unfortunately now I've lost the ability to construct an X
with an unshowable (a b)
.
Is there any way to allow X
to be constructed with any (a b)
, and then conditionally derive Show (X a)
only if (a b)
is showable?
This is a deficiency in the Prelude classes. There's a nice way around it though embodied in the prelude-extras
package. I'll outline it below.
We'd like to create a higher-kinded Show
class. It looks like this
class Show1 a where
show1 :: Show b => a b -> String
Then we can at least accurately express our desired constraint like
deriving instance Show1 a => Show (X a)
Unfortunately, the compiler does not yet have enough information to achieve this derivation. We need to show that (Show b, Show1 a)
is enough to derive Show (a b)
. To do so we'll need to enable some (scary, but sanely-used) extensions
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
instance (Show b, Show1 a) => Show (a b) where
show = show1
And now that we have that proof the compiler will be able to derive what we need
data X a = forall b . Show b => X (a b)
deriving instance Show1 a => Show (X a)
这篇关于有条件地派生Show对于在类型构造函数上参数化的存在类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!