throwE "escape 1" Just x -> do -6ren">
gpt4 book ai didi

haskell - 如果多个 monad 为 "mixed",是否可以利用 Monadic 结构?

转载 作者:行者123 更新时间:2023-12-02 21:28:50 24 4
gpt4 key购买 nike

考虑以下代码:

run = runExcept $ do
case Just 1 of
Nothing -> throwE "escape 1"
Just x -> do
case Just 2 of
Nothing -> throwE "escape 2"
Just y -> do
case Just 3 of
Nothing -> throwE "escape 3"
Just z -> return z

假设 Just 1Just 2Just 3 是返回 Maybe Int 的函数调用。

整个函数都在 ExceptT 内,因为我想抛出异常。但里面实际上只是很多被操纵的Maybe值。

那么,我是否可以利用 Maybe monad 的行为来避免楼梯外壳,同时仍然能够抛出异常?

最佳答案

您似乎想用与哪个失败(如果有)相关的信息来丰富一系列Maybe操作。为什么不将丰富实现为一个简单的函数?

enrich :: MonadError e m => e -> Maybe a -> m a
enrich e Nothing = throwError e
enrich e (Just x) = return x

我正在使用MonadError - monads m 类,可以抛出 e 类型的错误 - 泛化 enrich 的类型。例如,我们可以使用它,就好像它具有类型 e -> Maybe a -> except e ae -> Maybe a -> Either e a,因为 ExceptEither 都是 MonadError 的实例。

现在您只需使用 enrich 将您的 Maybe 值一次提升到更丰富的一元上下文中即可。

action = do
x <- enrich "escape 1" maybe1 -- look mum, no staircasing!
y <- enrich "escape 2" maybe2
z <- enrich "escape 3" maybe3
return [x, y, z]
<小时/>

如果您应用地使用您的单子(monad) - 也就是说,您没有使用早期的结果来确定以后的计算 - 有一种惯用的方法可以将此函数推广到任意数量的 也许。我们将把Maybes 以及我们需要丰富它的额外数据放入一个列表中 - 在本例中是错误消息。那么我们就可以traverse (née mapM )列表来丰富其中的每个也许并将它们连接成一个更大的单子(monad) Action 。

enrichMaybes :: (Traversable t, MonadError e m) => t (e, Maybe a) -> m (t a)
enrichMaybes = traverse (uncurry enrich)

action = enrichMaybes [("escape 1", maybe1), ("escape 2", maybe2), ("escape 3", maybe3)]

能够像这样将效果视为一等公民,这就是为什么函数式编程是一件好事。

关于haskell - 如果多个 monad 为 "mixed",是否可以利用 Monadic 结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35494202/

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