Why doesn't passing Nil to foldLeft work?

*爱你&永不变心* 提交于 2019-12-01 15:09:09

Scalas type inference engine works from left to right - therefore scalac can not infer the correct type for the first parameter list of foldLeft. You have to give the compiler a hint what type to use. Instead of using List[TYPE]() you can use List.empty[TYPE]:

(List(1,2,3) foldLeft List.empty[Int]) { (x,y) =>  y :: x }
(List.empty[Int] /: List(1, 2, 3)) { (x,y) => y :: x }

Scala's type inference works one parameter block at a time. Nil without any other context has no particular type, so the most restrictive type possible (Nothing) is chosen.

It also can't infer the return type of the function because the return type depends on the type of Nil. Getting out of that sort of circularity is tricky in general (if you don't specify what you mean).

There are a few tricks that you can apply, though, to make things less cumbersome.

First, the type signature of fold has only the type of the collection, so if you can use that sort of fold, you can get around the problem. For example, you could write your own reverse-flatten:

List(List(1),List(2),List(3)).fold(Nil)( (x,y) => y ::: x )

Second, if you're creating a new collection of the same type, it's often easier to use the existing collection to generate an empty one than to try to plug the types in for an empty collection. It's especially easy if you have pipe defined somewhere:

class PipeAnything[A](a: A) { def |>[B](f: A => B) = f(a) }
implicit def anything_can_be_piped[A](a: A) = new PipeAnything(a)

List(1,2,3) |> { x => x.foldLeft(x.take(0))( (y,z) => z :: y ) }

Finally, don't forget that you can define your own methods pretty easily that can do something consistent with your types, even if you have to use a bit of trickery to get it to work:

def foldMe[A,B](example: A, list: List[B])(f: (List[A],B) => List[A]) = {
  (List(example).take(0) /: list)(f)
}

scala> foldMe( ("",0), List("fish","wish","dish") )( (x,y) => (y.take(1), y.length) :: x )
res40: List[(java.lang.String, Int)] = List((d,4), (w,4), (f,4))

Here, note that the example is not a zero, but rather is only used as an exemplar of the thing with the type that you want.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!