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

bwr*_*oga 5 monads haskell 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
Run Code Online (Sandbox Code Playgroud)

我想将它们链接在一起,以便当一个函数的结果导致Nothing该函数的输入被返回时.

我可以用这个功能实现这个目的:

import Data.Maybe (fromMaybe)

e :: Int -> [Int -> Maybe Int] -> Int
e i [] = i
e i (f:fs) = e (fromMaybe i $ f i) fs
Run Code Online (Sandbox Code Playgroud)

-

*Main> e 75 [a,b,c]
75
Run Code Online (Sandbox Code Playgroud)

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

chi*_*chi 4

扩展我上面的评论——这种方法与OP发布的代码没有太大不同。

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

totalize :: (a -> Maybe a) -> (a -> a)
totalize f x = fromMaybe x (f x)
Run Code Online (Sandbox Code Playgroud)

然后,我们利用上面的内容:我们将每个函数设为“total”(意思是 no- Nothings),将其包装为 an Endo,然后我们组成自同态列表(mconcat是幺Endo半群中的组合)。

e :: [a -> Maybe a] -> a -> a
e = appEndo . mconcat . map (Endo . totalize)
Run Code Online (Sandbox Code Playgroud)

甚至(如下建议)

e :: Foldable t => t (a -> Maybe a) -> a -> a
e = appEndo . foldMap (Endo . totalize)
Run Code Online (Sandbox Code Playgroud)

  • `e = appEndo 。FoldMap(Endo.totalize)`? (2认同)