让:
{-# LANGUAGE RecursiveDo #-}
test :: [a] -> Maybe Int
test [] = Just 0
test (_ : xs) = mdo
unless (i == 0) Nothing -- 1
i <- test xs -- 2
Just i
我正在寻找有关为什么致电例如test "hey"
导致无限循环,并且通常会在处理mfix
时如何避免这种行为。另外,有没有一种方法可以更正前面的玩具示例,而无需交换(1)和(2)的顺序?
答案 0 :(得分:3)
这部分代码:
mdo unless (i == 0) Nothing
i <- test xs
Just i
减少对:
mfix (\i -> do unless (i == 0) Nothing
j <- test xs
Just j)
为了清楚起见,在i
表达式中将j
绑定到do
的绑定后。
第一条mfix
法则规定mfix f = _|_ iff f is strict
。在这种情况下,f
是:
\i -> do unless (i == 0) Nothing
j <- test xs
Just j
此功能很严格。 (如果用f
调用_|_
,将得到_|_
。)因此,其上的mfix
根据定义是_|_
。替换成您的原始照片,我们得到:
test [] = Just 0
test (_ : xs) = _|_
这表示除非您传递test
空列表,否则无论您传递给它什么其他输入,它都将始终存在差异。
当然,这就是理论方面。但是实际上,我不明白为什么您要进行这种递归,将递归定义的函数与monadic-value递归子部分混合在一起。除非仅仅是出于好奇,否则可能会有更好的方法来构建程序来避免此问题。但是为此,您必须共享更多有关您要真正实现的目标的信息。