I'm trying to change code that uses cats validation, something like:
case class Example(text: String, image: String)
case class ValidExample(text: String, image: String)
import cats.data.Validated._
import cats.implicits._
def validText(text: String) = if (text.nonEmpty) text.valid else invalid(-1)
def validImage(image: String) = if (image.endsWith(".png")) image.valid else invalid(-1)
val e = Example("test", "test.png")
(validText(e.text), validImage(e.image)).mapN(ValidExample)
Which works fine.
But my change requires the image field to be an Option, like:
case class Example(text: String, image: Option[String])
case class ValidExample(text: String, image: Option[String])
import cats.data.Validated._
import cats.implicits._
def validText(text: String) = if (text.nonEmpty) text.valid else invalid(-1)
def validImage(image: String) = if (image.endsWith(".png")) image.valid else invalid(-1)
val e = Example("test", Some("test.png"))
(validText(e.text), e.image.map(validImage)).mapN(ValidExample)
With this the mapN fails because the types suddenly differ, it says:
value mapN is not a member of (cats.data.Validated[Int,String], Option[cats.data.Validated[Int,String]])
I want it to only validate if the value exists. So it should be part of the validation result if value is present but ignore the field otherwise. I know there are some ways of combining validations but in my real code that would be much more involved than something like this.
Is there a way to do this in a simple manner? I haven't been able to find anything about it in the docs or in search.
Thanks for help!
cmd28.sc:1: type mismatch; found : String => cats.data.Validated[Int,String] required: String => G[B] val res28 = exampleWithImage.image.traverse(validImage) ^ cmd28.sc:1: Could not find an instance of Applicative for G val res28 = exampleWithImage.image.traverse(validImage)
– Tony Z Aug 07 '20 at 22:37