Original question
LYAH, in For a Few Monads More shows this function,
solveRPN :: String -> Maybe Double
solveRPN st = do
[result] <- foldM foldingFunction [] (words st)
return result
which uses pattern-matching in conjunction with do
expression to esure that the monad coming out of foldM
wraps a singleton list.
In order to truly understand the nature of the do
expression as well as of Monad
, I have been rewriting most example from that book using >>=
and >>
instead of the do
expression, a practice which is suggested somewhere in Real World Haskell too, but I don't remember which chapter.
As regards the function above, I'm a bit puzzled. What is the most concise way to write it without using the do
expression? The best I could come up with is
solveRPN :: String -> Maybe Double
solveRPN s = foldM step [] (words s) >>= \x -> case x of
[y] -> Just y
_ -> Nothing
but I was hoping in something cleaner, as this one is pretty noisy for 2 reasons:
- it uses a lambda
- it uses the
case
expression, which doesn't look much nicer than aif
-then
-else
.
This question is related to the present one.
I asked another question which actually highlights the basic issue in this one:
How do I pull the head
out of a list and succeed only for singleton lists?
And this has nothing to do with the Maybe
that wraps the result in solveRPN
.
Update
The answer I accepted there proposes a clear solution the question above:
func :: [a] -> a
func = foldr1 (const (const undefined))
which can be used to write easily solveRPN
in pointfree style:
solveRPN :: String -> Maybe Double
solveRPN st = foldM foldingFunction [] (words st) >>= Just . foldr1 (const (const undefined))
However, this absolutely unsatisfying, as it does not fully take advantage of the Maybe
monad, failing at runtime instead of returning Nothing
when the output is incorrect.
I think that playing around with that could lead me or someone else to answer my original question without do
/case
/helpers.