我认为问题只是该error
信息具有误导性。我们只关注MonadFix Maybe
. 参数mfix
可以是四件事之一。
在输入中可以是严格的:f _|_ = _|_
或者“f
需要评估它的输入来决定是否返回Nothing
或者Just
”
\x -> if x then Nothing else Just True
\x -> x `seq` Nothing
\x -> x `seq` Just x
可以const Nothing
。
可以Just . f
在f
不严格的地方。
Just . (1:)
它可以是严格的Just . f
地方。f
Just
如果函数是严格的,那么整个事情就会在无限循环中爆炸(就像fix
),并且看不到错误,因为我们不知道我们是否会有 aNothing
或 a Just
。如果是const Nothing
,则该函数实际上从未尝试评估error
并且什么也没有发生。如果它是Just . f
并且f
不严格,那么它只是Just $ fix f
(根据法律:)mfix $ return . f = return $ fix f
。而且,如果f
是严格的,我们得到Just _|_
(再次,根据法律)。请注意,我们从未看到error
触发。
类似的推理适用于MonadFix (MaybeT m)
. 我认为这次最好举个例子:
runMaybeT $ mfix $ \x -> MaybeT $
(x `seq` Nothing) :
Nothing :
(Just (1:x)) :
(Just x) :
(x `seq` [])
我上面列出的四个案例中的每一个都在该列表中。结果的第一个元素是无限循环。第二个是Nothing
。第三个是repeat 1
,第四个是Just
无限循环。尝试访问超出此范围的“元素”会触发另一个无限循环,这次是由[]
'sMonadFix
而不是MaybeT
's 引起的。同样,我不相信有可能触发error
,因为该函数必须在已经确定结果为 之后强制参数Nothing
。