避免在Haskell中monad中的模式匹配

时间:2012-10-03 13:58:49

标签: haskell functional-programming monads

我有以下定义:

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变换器?

2 个答案:

答案 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)