在foldl函数Haskell中添加Writer Monad

时间:2014-02-07 15:23:34

标签: haskell

我实现了一个搜索树内特定节点的函数。 这是功能,它的工作原理:

searchTree :: String -> Tree String -> Bool
searchTree value tree =
    foldl (\acc x -> if value `elem` x then True else acc) False (levels tree)


然后,我正在尝试实现相同的功能,但这一次,我想添加一个Writer Monad。这个不起作用,编译器说“无法匹配预期类型'Writer [String] Bool'与实际类型'Bool'” - >错误发生在第4行,在'return True'指令中。

searchTree :: String -> Tree String -> Writer [String] Bool
searchTree value tree =
    foldl (\acc x -> if value `elem` x then do
        tell ["My logger message "]
        return True else acc) return False (levels tree)

提前致谢。

2 个答案:

答案 0 :(得分:4)

return False周围缺少括号:

searchTree :: String -> Tree String -> Writer [String] Bool
searchTree value tree =
    foldl (\acc x -> if value `elem` x then do
        tell ["My logger message "]
        return True else acc) (return False) (levels tree)

提示:为了使这些错误更容易找到,我总是删除我的硬编码类型签名,因为问题可能是我误解了类型。在这种情况下,删除类型签名会将错误更改为:

Couldn't match expected type `Bool' with actual type `m0 a0' 
Expected type: a0 -> Bool 
Actual type: a0 -> m0 a0 
In the second argument of `foldl', namely `return'
In the expression:
    foldl (\acc x -> if value `elem` x then do
        tell ["My logger message "]
        return True else acc) (return False) (levels tree)

答案 1 :(得分:1)

请注意,在这些情况下,您(通常)确实希望使用foldr

searchTree :: String -> Tree String -> Writer [String] Bool
searchTree value tree =
    foldr (\x continue -> if value `elem` x then do
        tell ["My logger message "]
        return True else continue) (return False) (levels tree)

原因是,这不会检查整个列表,但是在第一个elem value x处停止,在大多数情况下(包括作者monad)将(>>=)与右侧关联比关联更有效在左侧,foldr与GHC的列表融合兼容,而foldl则不兼容。