简体   繁体   中英

Scala fold on a Sequence of a Tuple

I have the following method that I would like to apply fold operation on:

def rec(id: String, elems: Seq[(String, MyCase)]) = {
  elems.fold(Seq.empty[(String, Seq[String])] { elem =>
    ....
  }
}

What I do not get is the type of the elem is Nothing and I do not understand why it should be! Any clues?

You are missing the closing parentheses before the { , that's why your IDE, probably, thinks, the type is Nothing .

Also, you are, probably, looking for foldLeft , not fold (the first parameter of the latter must match the type of elements of the sequence).

Now the (simplified) signature of .foldLeft on Seq[A] is:

   foldLeft[B](b: B)(f: (B,A) => B)

As you can see, it takes a function, that transforms a Tuple2 into the type of the first parameter. The first element of the tuple has the same type as the first param, the second element is the same type as the elements of the sequence.

In your example, B is Seq[(String, Seq[String])] , and the sequence elements are (String, MyCase) . The type of input to the function would therefore take a horribly looking tuple like this:

(Seq[(String, Seq[String])], (String, MyCase))

This is caused by you are not only want to fold , you also you want to map the tuple , see the fold method signature:

  def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)

The input type and outtype must be same: A1 ,

so if want to map, you maybe want to try foldLeft :

def foldLeft[B](z: B)(op: (B, A) => B): B = 

There is a generics for output type B without bounding to A .

also we can find the fold source code is calling:

def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)

use foldLeft maybe like:

elements.fold(Seq.empty[(String, Seq[String])])((a, b) => a ++ Seq((b._1, Seq[String]())))

2nd EDIT: I'm an idiot. A fold must return the same value as the input type. Replace all the below folds with foldLefts for example and it works. You can't transform the data type in a standard fold. It was compiling for me but I didn't notice the return type was useless.

The second parameter in a fold is a function:

(ResultType, SingleElement) => Result Type

In this case

(Seq[(String, Seq[String])], Seq[(String, MyCase)]) => Seq[(String, Seq[String])]

Your code only has one input on the second parameter so the compiler doesn't know what it is. So it should look something like:

elems.foldLeft(Seq.empty[(String, Seq[MyCase])] {(zeroSeq, nextElem) =>
     //zeroSeq: Seq.empty[(String, Seq[MyCase]
     //nextElem: (String, MyCase)
}

EDIT:

The following for example compiles:

case class MyCase(x: String)
val elems: Seq[(String, MyCase)] = Seq(("Hi", MyCase("B")))

elems.foldLeft(Seq.empty[(String, Seq[MyCase])]){(z, s) =>
    z
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM