简体   繁体   中英

Haskell - Extract Maybe in Monad

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:

  • a^2 + b^2 = c^2
  • a + b + c = 1000

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM