2014-02-07 52 views
1

我实现了一个搜索树内特定节点的函数。 这里的功能和它的作品:在折叠函数中添加Writer Monad Haskell

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


于是,我试图实现相同的功能,但是这一次,我想补充一个作家单子。这一个不起作用,编译器显示“无法匹配期望的类型”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) 

在此先感谢。

回答

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) 
+0

为了清楚起见,我们应该补充一点,在修复显式类型签名之后,最好先将显式类型签名放回原处。 –

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,在大多数情况下(包括作家单子)关联(>>=)右边是比关联向左更高效,和foldr与GHC的列表融合兼容,而foldl则不兼容。