I am following the example in https://typelevel.org/cats/datatypes/validated.html but with a twist: the type of the elements in the NEL is not a DomainValidation but a DomainValidation[A] and I'm not sure how to do this. Below is my attempt but am having trouble with the types. This is probably just as much a Scala question as it is a Cats validated question.
import cats.data._
import cats.implicits._
sealed trait Widget
case object WidgetA extends Widget
case object WidgetB extends Widget
object Widget{
val values = List(WidgetA, WidgetB)
def fromString(s: String): Option[Widget] = values.filter(_.toString == s).headOption
}
case class Order( quantity: Float, widget: Widget )
trait MyValidation[A] {
def errorMessage: String
def is: A
}
type ValidationResult[A,B] = ValidatedNel[MyValidation[A], B]
case class WidgetQuantityIsNegative(is: Float) extends MyValidation[Float] {
def errorMessage = s"$is widget quantity is negative"
}
case class WidgetTypeIsInvalid(is: String) extends MyValidation[String] {
def errorMessage = s"$is is not a valid widget type"
}
def validateQuantity(q: Float): ValidationResult[Float, Float] =
if(q >= 0) q.validNel else WidgetQuantityIsNegative(q).invalidNel
/*
Here I would like to validate the string.
If it represents a valid Widget, return the valid Widget
else return the invalid */
def validateWidgetType(s: String) =
Widget.fromString(s) map {widget => widget.validNel } getOrElse WidgetTypeIsInvalid.invalidNel
def validateOrder( quantity: Float, s: String ): ValidationResult[MyValidation[Any], Order] = // NOT SURE IF ANY IS THE RIGHT TYPE
(
(validateQuantity(quantity)),
(validateWidgetType(s))
).mapN[Order](Order.apply) // THIS DOES NOT COMPILE