这是一些示例代码
foo :: a -> Identity (Maybe a)
foo a = do
maybeStuff <- getStuffSometimes a
return $ case maybeStuff of -- this "case" stuff is the kind
Just stuff -> Just $ getStuffAlways stuff -- of code I'd expect the Maybe
Nothing -> Nothing -- monad to help with
getStuffSometimes :: a -> Identity (Maybe a)
getStuffSometimes a = return $ Just a
getStuffAlways :: a -> Identity a
getStuffAlways = return
-- ERROR (on the return statement of the do block)
-- Expected type: Identity (Maybe a)
-- Actual type: Identity (Maybe (Identity a))
可能有点不清楚我要做什么,所以这里有一个更详细的描述:
所有有趣的东西都包装在一个计算上下文/容器中——在这种情况下,
Identity
为了演示。在我的实际代码中,我当然还有另一个单子。foo
并且getStuffSometimes
应该接受某种类型的东西a
并返回一个Maybe a
包装在上下文中的东西——也就是说,它们要么返回Identity (Just a)
(计算成功,要么Identity Nothing
(计算失败)。getStuffAlways
是一个永远不会失败的计算——它总是返回Identity a
。我想
foo
:- 运行失败的计算
- 如果可失败计算失败,则失败(无)
- 如果失败的计算成功,将它与 getStuffAlways 绑定,并返回
Just (result of getStuffAlways to the result of #1)
这是 Monad Transformers 的用例情况吗?在我的情况下,我的实际 monad 有点复杂,是我的库在 IO 之上提供的多个转换器堆栈,我不完全确定如何使它适用于这种情况(我会在另一个问题中问它结果是我必须使用变压器)
跟进:
在现实生活中,我有更多类似的东西:
foo :: a -> Identity (a, Maybe a)
foo a = do
firstPart <- getStuffAlways a
maybeStuff <- getStuffSometimes a
secondPart <- case maybeStuff of
Just stuff -> Just $ getStuffAlways stuff
Nothing -> Nothing
return (firstPart, secondPart)
在这种情况下,构建堆栈的最佳方法是什么?