是否有一种预定义的方法可以跳过导致 Nothing 的计算?
Is there a a predefined way to skip calculations that result in Nothing?
我有这三个功能
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 实例或其他方式?
您在寻找 maybe monad 吗?
*Main> let f x = a x >>= b >>= c >> return x
*Main> f 1
Just 1
*Main> f 100
Nothing
*Main>
然后,如果结果为 Nothing,我们可以使用 fromMaybe
(或只是 maybe
和 id
,同样的事情)达到您想要的最终状态:
*Main> let g x = maybe x id (f x)
*Main> g 100
100
好吧,您可以从 a -> Maybe a
:
创建一个 a -> 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
.
中获取值
扩展我上面的评论——这种方法与 OP 发布的代码没有太大区别。
我们首先定义如何将函数a -> Maybe a
转换为a -> a
,将输入替换为Nothing
。
totalize :: (a -> Maybe a) -> (a -> a)
totalize f x = fromMaybe x (f x)
然后,我们利用上面的:我们让每个函数 "total"(意思是没有-Nothing
s),把它包装成一个 Endo
,然后我们组成自同态列表(mconcat
是 Endo
幺半群中的组合)。
e :: [a -> Maybe a] -> a -> a
e = appEndo . mconcat . map (Endo . totalize)
甚至(如下所示)
e :: Foldable t => t (a -> Maybe a) -> a -> a
e = appEndo . foldMap (Endo . totalize)
我有这三个功能
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 实例或其他方式?
您在寻找 maybe monad 吗?
*Main> let f x = a x >>= b >>= c >> return x
*Main> f 1
Just 1
*Main> f 100
Nothing
*Main>
然后,如果结果为 Nothing,我们可以使用 fromMaybe
(或只是 maybe
和 id
,同样的事情)达到您想要的最终状态:
*Main> let g x = maybe x id (f x)
*Main> g 100
100
好吧,您可以从 a -> Maybe a
:
a -> 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
.
扩展我上面的评论——这种方法与 OP 发布的代码没有太大区别。
我们首先定义如何将函数a -> Maybe a
转换为a -> a
,将输入替换为Nothing
。
totalize :: (a -> Maybe a) -> (a -> a)
totalize f x = fromMaybe x (f x)
然后,我们利用上面的:我们让每个函数 "total"(意思是没有-Nothing
s),把它包装成一个 Endo
,然后我们组成自同态列表(mconcat
是 Endo
幺半群中的组合)。
e :: [a -> Maybe a] -> a -> a
e = appEndo . mconcat . map (Endo . totalize)
甚至(如下所示)
e :: Foldable t => t (a -> Maybe a) -> a -> a
e = appEndo . foldMap (Endo . totalize)