2016-09-12 70 views
3

這個scalaz tutorial提供了一個使用filterM方法的例子,但它不能解釋它。什麼是scalaz filterM方法?

List(1, 2, 3) filterM { x => List(true, false) } 
res19: List[List[Int]] = List(List(1, 2, 3), List(1, 2), List(1, 3), List(1), List(2, 3), List(2), List(3), List()) 

我看到我可以將它傳遞給任何大小的布爾列表。這是什麼filterM方法?

另外,是否有一本書/ scalaz教程多一點解釋?

回答

0

這是一個很老的問題。我只是回答,以防其他人想知道。

你可以從Learn You a Haskell for Good!找到一個很好的解釋。在我引用的鏈接中搜索filterM。

在這本書中,它說以下內容(你可以種做出來的Haskell語法):

過濾功能是相當多的Haskell編程的麪包(地圖是黃油)。它需要一個謂詞和一個列表來過濾掉,然後返回一個新的列表,只保留滿足謂詞的元素。其類型是這樣的:

濾波器::(一 - >布爾) - >並[a] - >並[a]

謂詞取列表的元素,並返回一個布爾值。現在,如果它返回的Bool值實際上是一個monadic值呢?哇!也就是說,如果它帶有上下文呢?這可以工作嗎?例如,如果謂詞產生的每個真或假值都具有伴隨的幺半羣值,如[「接受數字5」]或[「3太小」]呢?這聽起來像可以工作。如果是這種情況,我們希望得到的列表還會附帶所有在此過程中生成的日誌值的日誌。因此,如果謂詞返回的Bool帶有一個上下文,我們會期望最終的結果列表也附加了一些上下文,否則每個Bool附帶的上下文將會丟失。

filterM ::(單子米)=>(A - >米布爾) - >並[a] - > M [A]

該謂詞返回一個monadic值,其結果是布爾,但因爲它的一個單值,它的上下文可以是任何事物,從可能的失敗到非決定論等等!爲確保上下文反映在最終結果中,結果也是一個單值。

至於一本好書參考,我會閱讀下列Scalaz一個簡短的教程:Learning Scalaz。如果你需要更深入的解釋,我會回到學習你的haskell書。

對於我來說,在Scalaz的例子中,filterM確實沒有意義。從Haskell書中的解釋來看,這是完全合理的。

編輯:澄清什麼沒有意義。

1

根據實現,您需要傳遞函數A => F[Boolean],如F: ApplicativefilterM越過列表,爲謂詞傳遞的過濾元素(返回F[true]),並最終將此List轉換爲F

了一下簡單的例子:

List(1, 2, 3).filterM[Option](_.some.map(_ % 2 == 0)) // Some(List(2)) 

注意,這給你自由的額外程度,不能只考慮truefalse,但也None。您可以嘗試讓不同的應用程序掌握這個概念。

在您輸入的示例中,List也是Applicative。這樣,發生了什麼(因爲它是遞歸的,更容易從走到底):
1)當你在列表的末尾 - 你只是得到一個空列表
2)你有一個清單3 :: Nil。將謂詞應用到3會給你List(true, false)。所以,你正在採取整個List(3)和尾部List()
3)接下來是22 -> true :: false它映射到head :: head :: tail這就是List(2) :: List(2, 3)。追加到你以前的東西,你會得到List(List(2, 3), List(2), List(3), List())
4)現在是最後一步,你會得到一個。與true的列表中的每個列表相同,您可以將1添加到false的其餘列表中。

List(List(1, 2, 3), List(1, 2), List(1, 3), List(1), List(2, 3), List(2), List(3), List()) 

我加了一些記錄,弄清楚發生了什麼:

current list: List(1, 2, 3) 
current list: List(2, 3) 
current list: List(3) 
current list: List() 
filtered value: List(List()) 
taking head and tail : List(3) 
taking tail: List() 
filtered value: List(List(3), List()) 
taking head and tail : List(2, 3) 
taking head and tail : List(2) 
taking tail: List(3) 
taking tail: List() 
filtered value: List(List(2, 3), List(2), List(3), List()) 
taking head and tail : List(1, 2, 3) 
taking head and tail : List(1, 2) 
taking head and tail : List(1, 3) 
taking head and tail : List(1) 
taking tail: List(2, 3) 
taking tail: List(2) 
taking tail: List(3) 
taking tail: List() 
List(List(1, 2, 3), List(1, 2), List(1, 3), List(1), List(2, 3), List(2), List(3), List()) 
0

我不能完全肯定怎麼回事,但結果只是一個真值表。看起來好像filterM只是結合了兩個applicatives,其中一個是applicative of Boolean,所以基本上結果是適用於每個組合導致true

1,2,3 (true, true ,true) 
1,2  (true, true, false) 
2,3  (false, true, true) 
1,3  (true, false, true) 
1  (true, false, false) 
2  (false, true, false) 
3  (false, false, true) 
()  (false, false, false)