2
votes

I'm doing a simple exercise from the book Advanced scala with cats on my own.

I want to use Cartesian with Validated.

/*
this works
*/
type ValidatedString =  Validated[ Vector[String], String]
Cartesian[ValidatedString].product(
  "a".valid[Vector[String]],
  "b".valid[Vector[String]]
)

/* this doesnt work*/
type Result[A] = Validated[List[String], A]
Cartesian[ValidatedString].product(
    f(somevariable)//returns Result[String],
    g(somevariable)//returns Result[Int],
).map(User.tupled) // creates an user from the returned string, int

Im completely clueless. Any hints ? Im getting :

could not find implicit value for parameter instance: cats.Cartesian[Result] Cartesian[Result].product( ^

1
In your first example, you define ValidatedString in terms of Vector[], while in the second example, you define it in terms of List[]. Is this a real difference? - Bob Dalgleish
It's a minor point but your first code snippet doesn't actually work, since ValidatedString isn't a type constructor. It would make this question more useful to future readers to make sure that your code is described correctly. - Travis Brown

1 Answers

4
votes

Without seeing your imports I'd guess the issue is that you're missing a Semigroup instance for List (or Vector—it's not clear which you want to use), since the following works for me:

import cats.Cartesian, cats.data.Validated, cats.implicits._

type Result[A] = Validated[List[String], A]

Cartesian[Result].product(
  "a".valid[List[String]],
  "a".valid[List[String]]
)

You could replace the cats.implicits._ part with the following:

import cats.instances.list._
import cats.syntax.validated._

…but I'd suggest starting with cats.implicits._.

The problem here is that Validated accumulates failures when you combine two instances with product, and what "accumulates" means in a particular context is determined by a Semigroup instance for the invalid type that tells you how to "add" two invalid values together.

In the case of List (or Vector), concatenation makes sense for this accumulation operation, and Cats provides the concatenation Semigroup for any List[A], but in order to get it to be applied here you have to explicitly import it (either from cats.implicits or from cats.instances.list).