我有一个Haskell代码,它有两个函数:
第一个功能:
functionA :: [Int] -> Maybe Int
第二个:
functionB :: Int -> Maybe Int
我想要做的是递归[Int]的每个元素并将其提供给functionB。如果函数B返回一个Int,那么移动到下一个元素,如果它返回Nothing,那么functionA也不返回任何内容。
知道如何做到最好吗?
谢谢:)
答案 0 :(得分:3)
您可以使用sequence
将[Maybe Int]
带到Maybe [Int]
functionA ints = sequence (map functionB ints)
通常,sequence
和map
的这种组合称为mapM
。
functionA ints = mapM functionB ints
答案 1 :(得分:1)
你的问题有一些不清楚的事情因此我做了一些假设。
functionA
就像将[Int]
转换为Maybe Int
一样折叠,但在折叠整数之前,它会调用functionB
将每个整数转换为Maybe Int
其中Nothing
1}}结果表示转换失败,导致functionA
失败并使其返回Nothing
。
import Control.Applicative
functionA :: [Int] -> Maybe Int
functionA nums = foldl (\x y -> (+) <$> x <*> y) (Just 0) $ map functionB nums
functionB :: Int -> Maybe Int
functionB 2 = Nothing
functionB x = Just (x+x)
在上面的示例中,+
用于折叠操作,functionB
在数字2上失败
答案 2 :(得分:0)
学家亚伯拉罕森回答说得对,但是他把结果函数命名为异常并让你感到困惑。
让我们注意:
ints :: [a]
functionA :: [a] -> Maybe a
functionB :: a -> Maybe a
所以我们希望得到地图functionB
:
functionC :: a -> Maybe [a]
functionC ints = mapM functionB ints
但functionC
的结果类型为Maybe [a]
,而非[a]
,因此我们使用fmap
result :: [a] -> Maybe a
result ints = join $ fmap functionA $ functionC ints
我们还使用join
来删除Maybe (Maybe a)
结果
或者让我们写一行:
result :: [a] -> Maybe a
result = join . fmap functionA . mapM functionB
<强>已更新强>
但在此解决方案中始终计算所有ints
。
如果我们希望停止计算,我们需要mapIfAllJust
函数,如下所示:
result :: [a] -> Maybe a
result = join . fmap functionA . sequence . mapIfAllJust functionB
mapIfAllJust :: (a -> Maybe b) -> [a] -> [Maybe b]
mapIfAllJust _ [] = []
mapIfAllJust f (x:xs) = go f (f x) [] xs
where
go _ Nothing _ _ = [Nothing]
go _ pr used [] = pr : used
go f pr used (nxt:rst) = go f (f nxt) (pr : used) rst