Below is are two examples of mutually recursive function pairs. The first example terminates and produces the expected result. The second example is similar, except it uses the Maybe monad. fun1' does not terminate when called.
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.
Here are another two examples. Once again, the first example terminates with the expected result and the second example (using the Maybe monad) does not terminate.
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.
I believe I have a situation that is semantically similar to the last example in my real code. What are my options for getting it to terminate? Will I be forced to abandon the Maybe monad?
Update This is the solution I ended up using;
fun1'''' = do a <- Just [1]
b <- fun2''''
return $ b : a
fun2'''' = do return $ (head . tail . fromJust $ fun1'''') + 1
-- terminates :)
The key difference is that fun2''''
no longer operates on fun1''''
using the bind operator. Instead it explicitly uses fromJust (and assumes that fun1''''
is not Nothing
).
In my real code fun2
actually calls a number of other functions. These other functions are not mutually recursive with fun2
, and can potentially return a Nothing result. Fortunately I can still use the bind operator implicitly within the do notation for accessing the other required values.