我有以下定义:
env = DataMap.fromList [
("foo",42), ("bar",69),
("baz",27), ("qux",0)
]
doSomething:: String → Writer [String] Int
doSomething s = do
let v = DataMap.lookup s env
case v of
Nothing → fail $ s ++ " not found"
Just a → do
tell [s ++ " → " ++ (show a)]
return a
这段代码让我烦恼的是在doSomething中使用模式匹配。它完全违背了使用monad的目的。有没有办法只使用monadic函数重写doSomething函数而不使用monad变换器?
答案 0 :(得分:3)
正如@larsmans所说,最简单的方法是使用maybe
函数:
doSomething:: String -> Writer [String] Int
doSomething s = maybe n (\a -> t a >> return a) $ DataMap.lookup s env where
n = fail $ s ++ " not found"
t a = tell [s ++ " -> " ++ show a]
莫纳德变形金刚在这里帮助不大。你需要一个组合几个失败和写入的计算。如果只进行一次计算,则不需要monad。
另外,我使用ErrorT
转换器和throwError
函数来报告错误,而不是fail
。有关处理错误的可能方法,请参阅http://www.haskell.org/haskellwiki/Error_reporting_strategies。
答案 1 :(得分:0)
这有点笨重,但我就是这样做的。
doSomething2 :: String -> Writer [String] Int
doSomething2 s =
maybe (fail $ s ++ " not found") id $ do
a <- DataMap.lookup s env
return $ (tell [s ++ " -> " ++ show a] >> return a)