下面是兩個互相遞歸函數對的例子。第一個示例終止併產生預期的結果。第二個例子是類似的,除了它使用Maybe monad。 fun1'在被調用時不會終止。使用Maybe monad來終止相互遞歸函數
fun1 = 1 + fun2
fun2 = let x = fun1
in 2
-- terminates. result is 3.
fun1' = do a <- Just 1
b <- fun2'
return $ a + b
fun2' = do x <- fun1'
return 2
-- does not terminate.
這裏是另外兩個例子。再次,第一個示例終止於預期結果,第二個示例(使用Maybe monad)不終止。
fun1'' = fun2'' : [1]
fun2'' = (head . tail $ fun1'') + 1
-- terminates. result is [2,1]
fun1''' = do a <- Just [1]
b <- fun2'''
return $ b : a
fun2''' = do x <- fun1'''
return $ (head . tail $ x) + 1
-- does not terminate.
我相信我有一種情況,在語義上類似於我的真實代碼中的最後一個例子。我的選擇是什麼讓它終止?我會被迫放棄Maybe monad嗎?
更新 這是我最終使用的解決方案;
fun1'''' = do a <- Just [1]
b <- fun2''''
return $ b : a
fun2'''' = do return $ (head . tail . fromJust $ fun1'''') + 1
-- terminates :)
的關鍵區別是fun2''''
不再fun1''''
使用bind操作者操作。相反,它明確使用fromJust(並假定fun1''''
不是Nothing
)。
在我的真實代碼fun2
實際上調用了一些其他功能。這些其他函數與fun2
不相互遞歸,並且可能會返回Nothing結果。幸運的是,我仍然可以在符號中隱式使用bind運算符來訪問其他所需的值。
好吧,我明白你說的fun1/fun2實際上並不是相互遞歸的。這很有意義,因爲fun1實際上並不需要使用fun2來產生結果。但是,我會認爲fun1'/ fun2'可以被認爲是相互遞歸的,因爲如果沒有其他的結果,它們都不會產生結果。 – knick
@knick是的,你是對的。適當更新它。 – Sibi