如果我为import Foundation
定义monad转换器类型,则可以派生Identity
实例。
Show
将派生
newtype IdentityT f a =
IdentityT { runIdentityT :: f a }
deriving (Show)
但是如果我为instance Show (f a) => Show (IdentityT f a)
Maybe
我收到错误
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
deriving (Show)
由于• No instance for (Show (m (Maybe a)))
arising from the first field of ‘MaybeT’ (type ‘m (Maybe a)’)
有一个Maybe a
个实例,我希望它可以正常工作并推导
Show
为什么不能呢?
答案 0 :(得分:5)
我认为我们可以通过遵循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)’
好的,Show
MaybeT
可能不会导致 private TextInputLayout createNewOptionEntry() {
View parent = (View) binding.opt1InputLayout.getParent();
FrameLayout.LayoutParams fLayout = (FrameLayout.LayoutParams) parent.getLayoutParams();
TextInputLayout textInputLayout = new TextInputLayout(this);
textInputLayout.setLayoutParams(fLayout);
textInputLayout.setHint(count++ + ". Option");
LinearLayout.LayoutParams lLayout = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final TextInputEditText editText = new TextInputEditText(this);
editText.setLayoutParams(lLayout);
int id = View.generateViewId();
optionsViews.add(id);
editText.setId(id);
textInputLayout.addView(editText);
return textInputLayout;
}
,因为这种约束是不允许的,因为它是typechecker无法证明的那种约束终止约。你可以阅读更多关于什么&#34;不小于实例头&#34;在这个答案中意味着:https://stackoverflow.com/a/17866970/176841
答案 1 :(得分:3)
GHC使用启发式方法来确定实例是否保证搜索终止。 通过在此终止,我们的意思是,在搜索实例时,我们不会永远循环。具体而言,这必须是禁止的
instance Show a => Show a where ...
以及
instance Show [a] => Show a where ...
GHC大致要求实例上下文中的约束(=>
之前的部分)必须小于&#34;更小&#34;比头部的约束(=>
之后)。所以,它接受了这个:
instance Show a => Show [a] where ...
因为a
包含一个小于[a]
的类型构造函数。
它也接受这个:
instance Show (f a) => Show (IdentityT f a) where ...
因为f a
包含一个小于IdentityT f a
的类型构造函数。
然而,
instance Show (f (Maybe a)) => Show (MaybeT f a) where ...
使用相同数量的构造函数!因此,不能确定它不会导致循环。毕竟,以后,我们可能见面
instance Show (MaybeT f a)) => Show (f (Maybe a)) where ...
并且很清楚,必须拒绝这两个实例中的至少一个以保证终止。 GHC选择拒绝他们两个。
UndecidableInstances
放宽了这个限制。 GHC将接受这两个实例,现在我们要承担避免循环的负担。