首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Foldable的foldM?

如何使用Foldable的foldM?
EN

Stack Overflow用户
提问于 2017-04-15 17:36:49
回答 2查看 809关注 0票数 2

我试着通过一个简单的例子来理解cats中的foldM of Foldable:假设我需要对列表中的数字求和,而运行和是正的,而不是正的,则中断。

代码语言:javascript
复制
val sumUp: (Int, Int) => Option[Int] = (x, y) => {
  println(s"x = $x, y = $y")
  val sum = x + y
  if (sum > 0) Some(sum) else None 
} 

scala> val xs  = List(1, 2, 3, -2, -5, 1, 2, 3)
xs: List[Int] = List(1, 2, 3, -2, -5, 1, 2, 3)

scala> Foldable[Stream].foldM(xs.toStream, 0)(sumUp)
x = 0, y = 1
x = 1, y = 2
x = 3, y = 3
x = 6, y = -2
x = 4, y = -5
res27: Option[Int] = None

现在,我需要编写新的函数sumUp2来获取输入流的尾部,它从运行和变为<= 0和foldM中断的位置开始。例如,我需要获得如下内容:

代码语言:javascript
复制
scala> val tail = Foldable[Stream].foldM(xs.toStream, 0)(sumUp2)
tail: Stream[Int] = Stream(-5, ?)

scala>tail.toList
res28: List[Int] = List(-5, 1, 2, 3)

如何编写sumUp2

EN

回答 2

Stack Overflow用户

发布于 2017-04-15 21:23:47

您可以做的是累加两个值(在一个元组中):运行求和,直到它变为负数或零;以及尾部,它开始累加值。

代码语言:javascript
复制
val sumUp2: ((Int, List[Int]), Int) => Id[(Int, List[Int])] = (x, y) => {
  val sum = if (x._1 < 0) x._1 else x._1 + y
  if (sum > 0) (sum, x._2) else (-1, x._2 ++ List(y))
}

然后,您可以从元组中的第二个元素获得尾部:

代码语言:javascript
复制
val xs  = List(1, 2, 3, -2, -5, 1, 2, 3)
val res = Foldable[Stream].foldM(xs.toStream, (0, List[Int]()))(sumUp2)

println(res._2)

小提琴here

票数 3
EN

Stack Overflow用户

发布于 2017-04-16 00:46:30

我编写了sumUp2来返回Either[Int, (Int, Int)]:左边是访问的元素的数量,右边是访问的元素的数量和运行总和的对。

代码语言:javascript
复制
type IntOr[A] = Either[Int, A]
val sumUp2: ((Int, Int), Int) => IntOr[(Int, Int)] = (pair, y) => {
  val (size, x) = pair
  val sum = x + y
  println(s"sum = $sum, y = $y")
  if (sum > 0) (size + 1, sum).asRight else size.asLeft 
}

我们知道当sumUp2返回LeftfoldM会停止,所以不会对所有元素调用sumUp2

代码语言:javascript
复制
scala> val r = Foldable[Stream].foldM(xs.toStream, (0, 0))(sumUp2)
sum = 1, y = 1
sum = 3, y = 2
sum = 6, y = 3
sum = 4, y = -2
sum = -1, y = -5
r: IntOr[(Int, Int)] = Left(4)

给定r: Either[Int, (Int, Int)],我们可以得到尾部:

代码语言:javascript
复制
scala> r match { case Right(_) => Nil; case Left(n) => xs.drop(n) }
res63: List[Int] = List(-5, 1, 2, 3)

这个解决方案似乎工作得很好,但在我看来并不好。你会如何改进它?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43424502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档