2014-02-07 56 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則不兼容。