如果多个 monad 是 "mixed",是否可以利用 monadic 结构?
Is it possible to leverage monadic structure if multiple monads are "mixed"?
考虑以下代码:
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 1
、Just 2
、Just 3
是 return Maybe Int
的函数调用。
整个函数都在 ExceptT
中,因为我想抛出异常。但里面真的只是很多 Maybe
值被操纵。
那么,我是否可以利用 Maybe
monad 的行为来避免楼梯外壳,同时仍然能够抛出异常?
您似乎想要使用有关哪个失败 的信息来丰富一系列 Maybe
操作,如果有的话。为什么不将 enriching 作为一个简单的函数来实现?
enrich :: MonadError e m => e -> Maybe a -> m a
enrich e Nothing = throwError e
enrich e (Just x) = return x
我正在使用 MonadError
- monads m
的 class 可以抛出 e
类型的错误 - 以概括 enrich
的类型.例如,我们可以像使用 e -> Maybe a -> Except e a
或 e -> Maybe a -> Either e a
类型一样使用它,因为 Except
和 Either
都是 MonadError
.[=32 的实例=]
现在您只需要使用 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 applicatively - 也就是说,你没有使用早期的结果来确定以后的计算 - 有一种惯用的方法来概括这个函数来处理任意数量的 Maybe
。我们将把 Maybes
推入一个列表,连同我们需要的额外数据来丰富它——在本例中是错误消息。然后我们可以 traverse
(née mapM
) 列表来丰富其中的每个 Maybe
并将它们连接成一个更大的单子动作。
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)]
像这样将效果作为第一位 class 公民的能力就是为什么函数式编程是一件好事。
考虑以下代码:
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 1
、Just 2
、Just 3
是 return Maybe Int
的函数调用。
整个函数都在 ExceptT
中,因为我想抛出异常。但里面真的只是很多 Maybe
值被操纵。
那么,我是否可以利用 Maybe
monad 的行为来避免楼梯外壳,同时仍然能够抛出异常?
您似乎想要使用有关哪个失败 的信息来丰富一系列 Maybe
操作,如果有的话。为什么不将 enriching 作为一个简单的函数来实现?
enrich :: MonadError e m => e -> Maybe a -> m a
enrich e Nothing = throwError e
enrich e (Just x) = return x
我正在使用 MonadError
- monads m
的 class 可以抛出 e
类型的错误 - 以概括 enrich
的类型.例如,我们可以像使用 e -> Maybe a -> Except e a
或 e -> Maybe a -> Either e a
类型一样使用它,因为 Except
和 Either
都是 MonadError
.[=32 的实例=]
现在您只需要使用 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 applicatively - 也就是说,你没有使用早期的结果来确定以后的计算 - 有一种惯用的方法来概括这个函数来处理任意数量的 Maybe
。我们将把 Maybes
推入一个列表,连同我们需要的额外数据来丰富它——在本例中是错误消息。然后我们可以 traverse
(née mapM
) 列表来丰富其中的每个 Maybe
并将它们连接成一个更大的单子动作。
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)]
像这样将效果作为第一位 class 公民的能力就是为什么函数式编程是一件好事。