我正在绞尽脑汁想了解如何将State
monad 与Maybe
.
让我们从一个具体的(并且故意微不足道/不必要的)示例开始,在该示例中,我们使用State
monad 来查找数字列表的总和:
import Control.Monad.State
list :: [Int]
list = [1,4,5,6,7,0,3,2,1]
adder :: Int
adder = evalState addState list
addState :: State [Int] Int
addState = do
ms <- get
case ms of
[] -> return 0
(x:xs) -> put xs >> fmap (+x) addState
凉爽的。
现在让我们对其进行修改,使其Nothing
在列表包含数字时返回 a 0
。换句话说,evalState addState' list
应该返回Nothing
(因为list
包含 a 0
)。我以为它可能看起来像这样......
addState' :: State [Int] (Maybe Int)
addState' = do
ms <- get
case ms of
[] -> return (Just 0)
(0:xs) -> return Nothing
(x:xs) -> put xs >> fmap (fmap (+x)) addState'
...它有效,但我认为有更好的方法来做到这一点...
我玩过StateT
,MaybeT
但我无法让他们工作。我看过一些关于 Monad 变换器的介绍,但它们要么没有涉及这个特定的组合(即 State + Maybe),要么示例太复杂以至于我无法理解。
TL;DR:StateT
如果有人可以展示如何使用and MaybeT
(两个示例)编写这段(诚然微不足道的)代码,我将不胜感激。(我假设不使用转换器就不可能编写此代码 - 这是不正确的吗?)
PS我的理解是,这StateT
可能更适合这个例子,但从概念上看这两个例子会很有帮助,如果不是太麻烦的话。
更新:正如@Brenton Alker 所指出的,我上面的代码的第一个版本由于简单的错字(我缺少一个撇号)而不起作用。为了将问题集中在StateT
/的使用上MaybeT
,我正在更正上面的帖子。只是想包含这个注释来为他的帖子提供背景信息。