Haskell - 在 Monad 中提取 Maybe
Haskell - Extract Maybe in Monad
我正在研究 Project Euler 的问题 9,我有一个关于在另一个 monad 中提取 maybe 值的最佳方法的问题。题目要求找到'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' 可以通过分析计算,但是,由于它可能不存在,我 return 可能是一个值。
findC :: (Integral a) => a -> a -> Maybe a
findC a b = ... (implementation) ...
为了提取列表 monad 中的 maybe 值,我创建了以下函数:
fromJustM :: (Monad m) => Maybe a -> m a
fromJustM (Just a) = return a
fromJustM Nothing = fail ""
看起来这应该是一个常见的操作,那么是否有标准库函数可以执行此操作,或者是否有更惯用的方法来执行此操作?
fail
实际上不是单子操作;由于历史事故/隐藏一些肮脏的错误处理,它仅在 Monad
类型 class 中。
更合适的 class 是 MonadPlus
, or rather its Applicative
correspondent Alternative
. fail
translates to empty
。这样,您的签名实际上应该是
fromJustM' :: Alternative m => Maybe a -> m a
asum :: (Foldable t, Alternative f) => t (f a) -> f a
符合要求:Maybe
是 Foldable
。
c <- asum $ pure <$> findC a b
可以说,这实际上不是那么可读。
您实际上可以通过写作
更轻松地实现您的目标
Just c <- pure $ findC a b
这再次使用了 fail
方法:pattern-match 失败在 do
块中隐式调用它。
我正在研究 Project Euler 的问题 9,我有一个关于在另一个 monad 中提取 maybe 值的最佳方法的问题。题目要求找到'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' 可以通过分析计算,但是,由于它可能不存在,我 return 可能是一个值。
findC :: (Integral a) => a -> a -> Maybe a
findC a b = ... (implementation) ...
为了提取列表 monad 中的 maybe 值,我创建了以下函数:
fromJustM :: (Monad m) => Maybe a -> m a
fromJustM (Just a) = return a
fromJustM Nothing = fail ""
看起来这应该是一个常见的操作,那么是否有标准库函数可以执行此操作,或者是否有更惯用的方法来执行此操作?
fail
实际上不是单子操作;由于历史事故/隐藏一些肮脏的错误处理,它仅在 Monad
类型 class 中。
更合适的 class 是 MonadPlus
, or rather its Applicative
correspondent Alternative
. fail
translates to empty
。这样,您的签名实际上应该是
fromJustM' :: Alternative m => Maybe a -> m a
asum :: (Foldable t, Alternative f) => t (f a) -> f a
符合要求:Maybe
是 Foldable
。
c <- asum $ pure <$> findC a b
可以说,这实际上不是那么可读。
您实际上可以通过写作
更轻松地实现您的目标 Just c <- pure $ findC a b
这再次使用了 fail
方法:pattern-match 失败在 do
块中隐式调用它。