I am trying to find the most elegant way of converting the following stateful imperative piece of code to pure functional representation (preferably in Haskell to use abstraction that its Monad implementation offers). However I am not yet good at combining different monads using transformers and the like. It seems to me, that analyzing other's takes on such tasks helps the best when learning how to do it myself. The imperative code:
while (true) {
while (x = get()) { // Think of this as returning Maybe something
put1(x) // may exit and present some failure representation
}
put2() // may exit and present some success representation
}
When get
returns Nothing
we need the execution to continue with put2
, when get
returns Just x
we want the x
to get passed to put1
and short-circuit only if put1
fails or loop otherwise. Basically put1
and put2
may terminate the whole thing or move to the following statement changing the underlying state somehow. get
can either succeed and invoke put1
and loop or fail and continue to put2
.
My idea was something along:
forever $ do
forever (get >>= put1)
put2
And why I was looking for something like that is because (get >>= put1)
could simply short-circuit whenever get
has nothing to return or put1
terminates. Similarly put2
terminates the outer loop. However I am not sure how to mix the State
with the necessary Maybe
and/or Either
to achieve this.
I think using transformers to combine State
and the other monads is necessary and thus the code will most probably not be that succint. But I guess it as well might not be much worse.
Any suggestion how to achieve the translation elegantly is welcome. This differs from "Stateful loop with different types of breaks" in avoiding explicit control-flow using if
, when
, while
and rather tries to encourage use of Maybe
, Either
, or some other handy >>=
semantics. Also there is always a straight-forward way how to translate the code into a functional one, however it can hardly be considered elegant.