[英]Why can't the Show instance be derived for MaybeT?
If I define the monad transformer type for Identity
, it is able to derive the Show
instance. 如果我为
Identity
定义monad转换器类型,它可以派生Show
实例。
newtype IdentityT f a =
IdentityT { runIdentityT :: f a }
deriving (Show)
will derive 将衍生出来
instance Show (f a) => Show (IdentityT f a)
But if I define the monad transformer type for Maybe
但是如果我为
Maybe
定义monad变换器类型
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
deriving (Show)
I get the error 我收到了错误
• No instance for (Show (m (Maybe a)))
arising from the first field of ‘MaybeT’ (type ‘m (Maybe a)’)
Since Maybe a
has a Show
instance, I would expect it to work and derive 由于
Maybe a
有一个Show
实例,我希望它可以工作并派生出来
instance Show (m (Maybe a)) => Show (MaybeT m a)
Why can't it? 为什么不能呢?
I think we can see the issue by following GHC's suggestions (I'm using 8.2.1) until we hit a dead end: 我想我们可以通过遵循GHC的建议(我正在使用8.2.1)看到这个问题,直到我们走到尽头:
Prelude> :{
Prelude| newtype MaybeT m a =
Prelude| MaybeT { runMaybeT :: m (Maybe a) }
Prelude| deriving (Show)
Prelude| :}
<interactive>:12:13: error:
• No instance for (Show (m (Maybe a)))
arising from the first field of ‘MaybeT’ (type ‘m (Maybe a)’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Show (MaybeT m a))
Prelude> :set -XStandaloneDeriving
Prelude> deriving instance Show (m (Maybe a)) => Show (MaybeT m a)
<interactive>:17:19: error:
• The constraint ‘Show (m (Maybe a))’
is no smaller than the instance head
(Use UndecidableInstances to permit this)
• In the stand-alone deriving instance for
‘Show (m (Maybe a)) => Show (MaybeT m a)’
Okay, so Show
wasn't derivable for MaybeT
likely because that constraint would have been disallowed, as it's the sort of constraint the typechecker can't prove termination about. 好的,所以
Show
可能不会导致MaybeT
因为这种约束是不允许的,因为它是类型检查器无法证明终止的约束。 You can read more about what "no smaller than instance head" means in this answer: https://stackoverflow.com/a/17866970/176841 您可以在此答案中详细了解“不小于实例头”的含义: https : //stackoverflow.com/a/17866970/176841
GHC uses a heuristics to determine if an instance guarantees search termination. GHC使用启发式方法来确定实例是否保证搜索终止。 By termination here, we mean that, when searching for an instance we will not loop forever.
通过在此终止,我们的意思是,在搜索实例时,我们不会永远循环。 Concretely,this must be forbidden
具体而言,必须禁止这样做
instance Show a => Show a where ...
as well as this 以及这个
instance Show [a] => Show a where ...
GHC roughly requires that constraints in the instance context (the part before the =>
) must be "smaller" than the constraint in the head (after the =>
). GHC粗略地要求实例上下文中的约束(
=>
之前的部分)必须比头部中的约束“更小”(在=>
)。 So, it accepts this: 所以,它接受这个:
instance Show a => Show [a] where ...
since a
contains one type constructor less than [a]
. 因为
a
包含一个小于[a]
类型构造函数。
It also accepts this: 它也接受这个:
instance Show (f a) => Show (IdentityT f a) where ...
since fa
contains one type constructor less than IdentityT fa
. 因为
fa
包含一个小于IdentityT fa
类型构造函数。
However, 然而,
instance Show (f (Maybe a)) => Show (MaybeT f a) where ...
uses the same number of constructors! 使用相同数量的构造函数! Hence, it is not accepted to be sure it will not cause a loop.
因此,不能确定它不会导致循环。 After all, later on, we might meet
毕竟,以后,我们可能会见面
instance Show (MaybeT f a)) => Show (f (Maybe a)) where ...
and it's clear that at least one of these two instances must be rejected to guarantee termination. 并且很明显,必须拒绝这两个实例中的至少一个以保证终止。 GHC chooses to reject both of them.
GHC选择拒绝他们两个。
UndecidableInstances
relaxes this restriction. UndecidableInstances
放宽了这个限制。 GHC will accept both instances, and now the burden is on us to avoid loops. GHC将接受这两个实例,现在我们要承担避免循环的负担。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.