是否有预定义的方法来跳过导致无效的计算?

时间:2016-10-27 15:13:33

标签: haskell monads maybe

我有这三个功能

a :: Int -> Maybe Int
a i = if i < 100 then Just i else Nothing

b :: Int -> Maybe Int
b i = if i < 50 then Just i else Nothing

c :: Int -> Maybe Int
c i = if i > 0 then Just i else Nothing

我希望将它们链接在一起,这样当一个函数的结果导致Nothing时,将返回该函数的输入。

我可以通过此功能实现此目的:

import Data.Maybe (fromMaybe)

e :: Int -> [Int -> Maybe Int] -> Int
e i [] = i
e i (f:fs) = e (fromMaybe i $ f i) fs

-

*Main> e 75 [a,b,c]
75

是否存在显示此行为的基本库中的现有函数,Monad实例或其他方式?

3 个答案:

答案 0 :(得分:4)

扩展我的评论 - 这种方法与OP发布的代码并无太大差别。

我们首先定义如何将函数a -> Maybe a转换为a -> a,将输入替换为Nothing

totalize :: (a -> Maybe a) -> (a -> a)
totalize f x = fromMaybe x (f x)

然后,我们利用上面的内容:我们将每个函数都设为“total”(意思是没有 - Nothing s),将其包装为Endo,然后我们编写内部构造列表({{1 }}是mconcat monoid中的组合。

Endo

或甚至(如下所述)

e :: [a -> Maybe a] -> a -> a
e = appEndo . mconcat . map (Endo . totalize)

答案 1 :(得分:2)

好吧,您可以从a -> a创建a -> Maybe a

repair :: (a -> Maybe a) -> a -> a
repair f x = fromMaybe x (f x)

之后,您只需合并(.)repair

andThen :: (a -> Maybe a) -> (a -> Maybe a) -> a -> a
andThen f g = repair g . repair f

但是没有库函数,因为没有通用的方法可以从Monad中获取值。

答案 2 :(得分:0)

你在找monad吗?

*Main> let f x = a x >>= b >>= c >> return x
*Main> f 1
Just 1
*Main> f 100
Nothing
*Main>

然后,如果结果为Nothing,我们可以使用fromMaybe(或仅maybeid来达到您想要的最终状态,同样的事情):

*Main> let g x = maybe x id (f x)
*Main> g 100
100