gpt4 book ai didi

haskell - 在管道上运行 `sequence`

转载 作者:行者123 更新时间:2023-12-05 03:18:22 25 4
gpt4 key购买 nike

我有一个效果的函数:

f :: a -> Either b c

我想构建这种类型的管道:

ConduitT a c m (Maybe b)

基本上,我们有一个 a 流,我想生成一个 c 流,但是在错误 b .

如果我使用列表,我基本上就是在创建一个函数

[a] -> Either b [c]

这很简单,只需 sequence 。 (图 f)

但我无法将其转换为管道。有什么想法吗?

最佳答案

首先,考虑您是否真的想返回可能是b,或者您是否想在monad m 中引发错误。如果是后者,那么您可能实际上想要:

mapMC :: Monad m => (a -> m b) -> ConduitT a b m ()

它直接将 f::a -> Either b c 转换为:

mapMC f :: ConduitT a c (Either b) ()

或者对于一个更通用的 m,在堆栈中有一个 ExceptT 转换器:

mapMC (liftEither . f) :: (MonadError b m) => ConduitT a c m ()

如果你决定,不,你真的想要一个 Maybe b 返回类型,那么下面的方法可能会起作用:

import Conduit

whileRightC :: (Monad m) => (a -> Either b c) -> ConduitT a c m (Maybe b)
whileRightC f = mapAccumWhileC step Nothing
where step a _ = case f a of Right c -> Right (Nothing, c)
Left b -> Left (Just b)

或者,您可以像这样使用 Data.Conduit.Lift 中的函数将 mapMC 生成的 monadic 异常转换为 Either您可以转换为 Maybe 的值:

import Conduit
import Control.Monad.Trans.Except (except)

whileRightC :: (Monad m) => (a -> Either b c) -> ConduitT a c m (Maybe b)
whileRightC f = do
r <- runExceptC $ mapMC (except . f)
return $ case r of
Left err -> Just err
Right () -> Nothing

如果性能至关重要,您可能需要对这两个版本的 whileRightC 进行基准测试,看看哪个更快。

关于haskell - 在管道上运行 `sequence`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73724849/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com