这个scalaz tutorial提供了使用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 :(得分:1)
根据实施,您需要传递函数A => F[Boolean]
,例如F: Applicative
。
filterM
遍历列表,过滤了传递谓词的元素(返回F[true]
),最后将此List
放入F
。
一个更简单的例子:
List(1, 2, 3).filterM[Option](_.some.map(_ % 2 == 0)) // Some(List(2))
请注意,这不仅可以考虑true
或false
,还可以None
,从而为您提供额外的自由度。您可以尝试不同的应用程序来掌握这个概念。
在您输入的示例中,List
也是Applicative。那么,会发生什么(因为它是递归的,更容易从最后开始):
1)当你在列表的末尾时 - 你只得到一个空列表
2)你有一个列表3 :: Nil
。将谓词应用于3
会为您提供List(true, false)
。所以,你正在考虑整个List(3)
和尾部List()
3)接下来是2
。 2 -> true :: false
映射到head
:: head :: tail
List(2) :: List(2, 3)
。将其添加到您之前的内容中,您将获得List(List(2, 3), List(2), List(3), List())
4)现在是最后一步,你得到一个。将1
添加到true
的每个列表中的方式与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())
答案 1 :(得分: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)
答案 2 :(得分:0)
这是一个非常古老的问题。我会回答以防万一其他人在想。
你可以从Learn You a Haskell for Good!找到一个很好的解释。在我引用的链接中搜索filterM。
在书中,它说明了以下内容(你可以看出haskell语法):
过滤功能几乎是Haskell编程的一部分(地图是黄油)。它需要一个谓词和一个列表来过滤掉然后返回一个新列表,其中只保留满足谓词的元素。它的类型是:
filter ::(a - > Bool) - > [a] - > [a]
谓词采用列表的元素并返回Bool值。现在,如果它返回的Bool值实际上是monadic值怎么办?哇!也就是说,如果它带有上下文怎么办?这可行吗?例如,如果谓词产生的每个True或False值都具有伴随的monoid值,如[“Accepted the number 5”]或[“3 is too small”],该怎么办?听起来它可以工作。如果是这种情况,我们希望结果列表还附带一路上记录的所有日志值。因此,如果谓词返回的Bool带有上下文,我们期望最终结果列表也附加一些上下文,否则每个Bool附带的上下文将丢失。
filterM ::(Monad m)=> (a - > m Bool) - > [a] - > m [a]
谓词返回一个monadic值,其结果是Bool,但由于它是一个monadic值,它的上下文可以是从可能的失败到非确定性等等!为了确保上下文反映在最终结果中,结果也是一个monadic值。
至于一本好书供参考,我会阅读以下Scalaz的简要教程:Learning Scalaz。如果你需要进一步深入解释,我会回到学习你的哈克尔书。
对于我来说,对于Scalaz示例中的filterM做什么仍然没有意义。根据Haskell书中的解释,它完全有道理。
编辑:明确了什么没有意义。