# [Haskell-cafe] How do I do conditional tail recursion in a monad?

Jules Bean jules at jellybean.co.uk
Wed Mar 21 05:31:26 EDT 2007

```DavidA wrote:
> So I figure untilM should look something like:
> untilM :: Monad m => (a -> Bool) -> (a -> m a) -> a -> m a
> untilM p f x = return (if p x then x else untilM p f (f x))
> The problem is that the two branches of the conditional have different types.
> If I try to remedy that by changing "then x" to "then return x", it still isn't
> happy.
>
>

This makes a m (m a). The following is closer:

*Main> :t let untilM p f x = if p x then return x else untilM p f (f x)
in untilM
let untilM p f x = if p x then return x else untilM p f (f x) in untilM
:: (Monad m) => (a -> Bool) -> (a -> a) -> a -> m a

...but here 'f' is a pure function, not a monadic action. If you want f
to be a monadic action then you want:

*Main> :t let untilM p f x = if p x then return x else untilM p f =<< f
x in untilM
let untilM p f x = if p x then return x else untilM p f =<< f x in
untilM :: (Monad m) => (a -> Bool) -> (a -> m a) -> a -> m a

(if you prefer do notation to explicit binds, rewrite "untilM p f =<< f
x" as "y <- f x ; untilM p f y")

> (My real question is, how do I do conditional tail recursion in a monad?)
>

actually I don't think that was your real question :) Your real question