Reputation: 23
I am working on problem 9 of Project Euler, and I have a question about the best way to extract a maybe value inside another monad. The problem asks to find 'a', 'b', 'c' that satisfy:
I have written the following code that solves the problem:
problem9 :: (Integral a) => a -> [(a, a, a)]
problem9 n =
do
a <- [1..n]
b <- [1..a]
c <- fromJustM (findC a b)
guard (a + b + c == n)
return (a, b, c)
'c' can be computed analytically, but, since it may not exist, I return a maybe value.
findC :: (Integral a) => a -> a -> Maybe a
findC a b = ... (implementation) ...
To extract the maybe value inside the list monad, I have created the following function:
fromJustM :: (Monad m) => Maybe a -> m a
fromJustM (Just a) = return a
fromJustM Nothing = fail ""
It seems like this should be a common operation, so is there a standard library function that does this, or is there a more idiomatic way to do it?
Upvotes: 2
Views: 485
Reputation: 120741
fail
is not actually a monadic operation; it's only in the Monad
type class because of historic accident / to hide some dirty error handling.
A more proper class for this is MonadPlus
, or rather its Applicative
correspondent Alternative
. fail
translates to empty
. With that, your signature should in fact be
fromJustM' :: Alternative m => Maybe a -> m a
to which Hoogle offers
asum :: (Foldable t, Alternative f) => t (f a) -> f a
Which fits the bill: Maybe
is a Foldable
.
c <- asum $ pure <$> findC a b
Arguably, this is not in fact that readable.
You can actually achieve your goal much easier by writing
Just c <- pure $ findC a b
This does again use the fail
method: pattern-match failure in a do
block calls it implicitly.
Upvotes: 6