I have been trying to traverse a data structure in Scala and do two things at the same time. I have been using Cats library for this. Here's a little example which does not compile. I do not understand how I could make this work. Any help is greatly appreciated.
import cats.data.Tuple2K
import cats.data.Const
import cats.syntax.traverse._
List("A", "BB", "CCC").traverse[Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing], Nothing]{
case str =>
Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing](Const(1), Const(str.size))
}
The tools throw the following error:
Found: cats.data.Tuple2K[[x] =>> cats.data.Const[Int, x], [x] =>> cats.data.Const[Int, x], Nothing]
Required: cats.data.Tuple2K[[x] =>> cats.data.Const[Int, x], [x] =>> cats.data.Const[Int, x], Nothing][Nothing]
I am trying to get both the size of the traversable (the above list in my example) and perform some content based computations in one traversal only, as opposed to traverse the list twice.
Update Following the initial responses to my post, I decided to offer a bit more clarity through this update.
To be clear, if I remove the explicit type parameters, the code compiles and does what I expect it to do:
import cats.data.Tuple2K
import cats.data.Const
import cats.syntax.traverse._
List("A", "BB", "CCC").traverse{
case str =>
Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing](Const(1), Const(str.size))
} // Tuple2K(Const(3),Const(6)) which is of type Tuple2K[[x >: Nothing <: Any] => Const[Int, x], [x >: Nothing <: Any] => Const[Int, x], List[Nothing]] !!!
My problem with the initial code snippet is that those types are the ones that are inferred by the compiler anyway, so passing them explicitly should just work.
I really don't understand why are you trying to specify all those types yourself by hand. The whole point of type inference is to avoid specifying these kind of repetitive and annoying type and still be typesafe.
Anyways the type signature you want is this:
List("A", "BB", "CCC").traverse[[x] =>> Tuple2K[[y] =>> Const[Int, y], [y] =>> Const[Int, y], x], Nothing] {
case str =>
Tuple2K[[x] =>> Const[Int, x], [x] =>> Const[Int, x], Nothing](Const(1), Const(str.size))
}
That is because traverse
requires two types a type constructor G[_]
of kind * -> *
and a normal type B
of kind *
.
In this case your G[_]
is:
[x] =>> Tuple2K[
[y] =>> Const[Int, y],
[y] =>> Const[Int, y],
x
]
You can see the code running here: https://scastie.scala-lang.org/BalmungSan/byuGYrQUTaC4HvXYA8WhNw/3