我有以下定义:
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 的目的。有没有办法只使用单子(monad)函数而不使用单子(monad)转换器来重写 doSomething 函数?
最佳答案
正如@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 转换器在这里没有什么帮助。您将需要一个来组合几个既失败又写入的计算。如果只有一次计算,则不需要 monad。
此外,我会使用 ErrorT
转换器和 throwError
函数来报告错误,而不是 fail
。请参阅http://www.haskell.org/haskellwiki/Error_reporting_strategies了解处理错误的可能方法。
关于haskell - 避免 Haskell 中 monad 内的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12710127/