Haskell - 提取可能在Monad

时间:2016-01-25 00:20:03

标签: haskell monads

我正在研究Project Euler的问题9,我对在另一个monad中提取一个可能值的最佳方法有疑问。问题要求找到满足的“a”,“b”,“c”:

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

我编写了以下代码来解决问题:

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'可以通过分析计算,但由于它可能不存在,我会返回一个可能的值。

findC :: (Integral a) => a -> a -> Maybe a
findC a b = ... (implementation) ...

要提取列表monad中的可能值,我创建了以下函数:

fromJustM :: (Monad m) => Maybe a -> m a
fromJustM (Just a) = return a
fromJustM Nothing = fail ""

看起来这应该是一个常见的操作,所以有没有一个标准的库函数可以做到这一点,还是有更惯用的方法呢?

1 个答案:

答案 0 :(得分:6)

fail实际上不是一个monadic操作;它只是在Monad类型类中,因为历史意外/隐藏了一些脏的错误处理。

更合适的类是MonadPlus,或者更确切地说是Applicative通讯员Alternativefail转换为empty。有了这个,你的签名实际上应该是

fromJustM' :: Alternative m => Maybe a -> m a

Hoogle offers

asum :: (Foldable t, Alternative f) => t (f a) -> f a

符合条件的是:MaybeFoldable

        c <- asum $ pure <$> findC a b

可以说,这实际上并不可读。

通过编写

,您可以更轻松地实现目标
        Just c <- pure $ findC a b

这再次使用fail方法:do块中的模式匹配失败会隐式调用它。