I am trying to validate a list of strings sequentially and define the validation result type like that:
import cats._, cats.data._, cats.implicits._
case class ValidationError(msg: String)
type ValidationResult[A] = Either[NonEmptyList[ValidationError], A]
type ListValidationResult[A] = ValidationResult[List[A]] // not a monad :(
I would like to make ListValidationResult a monad. Should I implement flatMap and pure manually or there is an easier way ?
I suggest you to take a totally different approach leveraging cats Validated:
import cats.data.Validated.{ invalidNel, valid }
val stringList: List[String] = ???
def evaluateString(s: String): ValidatedNel[ValidationError, String] =
if (???) valid(s) else invalidNel(ValidationError(s"invalid $s"))
val validationResult: ListValidationResult[String] =
stringList.map(evaluateString).sequenceU.toEither
It can be adapted for a generic type T, as per your example.
Notes:
val stringList: List[String] = ??? is the list of strings you want to validate;
ValidatedNel[A,B] is just a type alias for Validated[NonEmptyList[A],B];
evaluateString should be your evaluation function, it is currently just an unimplemented stub if;
sequenceU you may want to read cats documentation about it: sequenceU;
toEither does exactly what you think it does, it converts a Validated[A,B] to an Either[A,B].
As #Michael pointed out, you could also use traverseU instead of map and sequenceU
val validationResult: ListValidationResult[String] =
stringList.traverseU(evaluateString).toEither
Related
I have an implicit class that decodes server's response into a JSON and latter in the right case class to avoid repeating calls to .as and .getOrElse all around the tests:
implicit class RouteTestResultBody(testResult: RouteTestResult) {
def body: String = bodyOf(testResult)
def decodedBody[T](implicit d: Decoder[T]): T =
decode[Json](body)
.fold(err => throw new Exception(s"Body is not a valid JSON: $body"), identity)
.as[T]
.getOrElse(throw new Exception(s"JSON doesn't have the right shape: $body"))
}
Of course, it relies on us passing a decoder:
import io.circe.generic.semiauto.deriveDecoder
val result: RouteTestResult = ...
result.decodedBody(deriveDecoder[SomeType[AnotherType])
It works most of the time, but fails when the response is a list:
result.dedoceBody(deriveDecoder[List[SomeType]])
// throws "JSON doesn't have the right shape"
How can I semiautomatically derive a decoder for a list with specific types inside?
The terminology here is unfortunately overloaded, in that we use "deriving" in two senses:
Providing an instance for e.g. List[A] given an instance for A.
Providing an instance for a case class or sealed trait hierarchy given instances for all member types.
This problem isn't specific to Circe, or even Scala. In writing about Circe I generally try to avoid referring to the first kind of instance generation as "derivation" at all, and to refer to the second kind as "generic derivation" to emphasize that we're generating instances via a generic representation of the algebraic data type.
The fact that we sometimes use the same word to refer to both kinds of type class instance generation is a problem because they're typically very distinct mechanisms in Scala. In Circe the thing that provides an encoder or decoder instance for List[A] given one for A is a method in the type class companion object. For example, in the object Decoder in circe-core we have a method like this:
implicit def decodeList[A](implicit decodeA: Decoder[A]): Decoder[List[A]] = ...
Because this method definition is in the Decoder companion object, if you ask for an implicit Decoder[List[A]] in a context where you have an implicit Decoder[A], the compiler will find and use decodeList. You don't need any imports or extra definitions. For example:
scala> case class Foo(i: Int)
class Foo
scala> import io.circe.Decoder, io.circe.parser
import io.circe.Decoder
import io.circe.parser
scala> implicit val decodeFoo: Decoder[Foo] = Decoder[Int].map(Foo(_))
val decodeFoo: io.circe.Decoder[Foo] = io.circe.Decoder$$anon$1#6e992c05
scala> parser.decode[List[Foo]]("[1, 2, 3]")
val res0: Either[io.circe.Error,List[Foo]] = Right(List(Foo(1), Foo(2), Foo(3)))
If we desugared the implicit machinery here, it would look like this:
scala> parser.decode[List[Foo]]("[1, 2, 3]")(Decoder.decodeList(decodeFoo))
val res1: Either[io.circe.Error,List[Foo]] = Right(List(Foo(1), Foo(2), Foo(3)))
Note that we could replace first kind of derivation with the second, and it would still compile:
scala> import io.circe.generic.semiauto.deriveDecoder
import io.circe.generic.semiauto.deriveDecoder
scala> parser.decode[List[Foo]]("[1, 2, 3]")(deriveDecoder[List[Foo]])
val res2: Either[io.circe.Error,List[Foo]] = Left(DecodingFailure(CNil, List()))
This compiles because Scala's List is an algebraic data type that has a generic representation that circe-generic can create an instance for. The decoding fails for this input, though, since this representation doesn't result in the encoding we expect. We can derive the corresponding encoder to see what this encoding looks like:
scala> import io.circe.Encoder, io.circe.generic.semiauto.deriveEncoder
import io.circe.Encoder
import io.circe.generic.semiauto.deriveEncoder
scala> implicit val encodeFoo: Encoder[Foo] = Encoder[Int].contramap(_.i)
val encodeFoo: io.circe.Encoder[Foo] = io.circe.Encoder$$anon$1#2717857a
scala> deriveEncoder[List[Foo]].apply(List(Foo(1), Foo(2)))
val res3: io.circe.Json =
{
"::" : [
1,
2
]
}
So we're actually seeing the :: case class for List, which is basically never what we want.
If you need to provide a Decoder[List[Foo]] explicitly, the solution is to use either the Decoder.apply "summoner" method, or to call Decoder.decodeList explicitly:
scala> Decoder[List[Foo]]
val res4: io.circe.Decoder[List[Foo]] = io.circe.Decoder$$anon$44#5d40f590
scala> Decoder.decodeList[Foo]
val res5: io.circe.Decoder[List[Foo]] = io.circe.Decoder$$anon$44#2f936a01
scala> Decoder.decodeList(decodeFoo)
val res6: io.circe.Decoder[List[Foo]] = io.circe.Decoder$$anon$44#7f525e05
These all provide exactly the same instance, and which you should choose is a matter of taste.
As a footnote, I've thought about special-casing List in circe-generic so that deriveDecoder[List[X]] doesn't compile, since it's approximately never what you want (but seems like it might be, especially because of the confusing way we talk about instance derivation). I typically don't like the idea of having special cases like that, but I think in this case it might be the right thing to do, since this question comes up a lot.
Here is an example from the Scala with Cats book:
object Ex {
import cats.data.Validated
type FormData = Map[String, String]
type FailFast[A] = Either[List[String], A]
def getValue(name: String)(data: FormData): FailFast[String] =
data.get(name).toRight(List(s"$name field not specified"))
type NumFmtExn = NumberFormatException
import cats.syntax.either._ // for catchOnly
def parseInt(name: String)(data: String): FailFast[Int] =
Either.catchOnly[NumFmtExn](data.toInt).leftMap(_ => List(s"$name must be an integer"))
def nonBlank(name: String)(data: String): FailFast[String] =
Right(data).ensure(List(s"$name cannot be blank"))(_.nonEmpty)
def nonNegative(name: String)(data: Int): FailFast[Int] =
Right(data).ensure(List(s"$name must be non-negative"))(_ >= 0)
def readName(data: FormData): FailFast[String] =
getValue("name")(data).
flatMap(nonBlank("name"))
def readAge(data: FormData): FailFast[Int] =
getValue("age")(data).
flatMap(nonBlank("age")).
flatMap(parseInt("age")).
flatMap(nonNegative("age"))
case class User(name: String, age: Int)
type FailSlow[A] = Validated[List[String], A]
import cats.instances.list._ // for Semigroupal
import cats.syntax.apply._ // for mapN
def readUser(data: FormData): FailSlow[User] =
(
readName(data).toValidated,
readAge(data).toValidated
).mapN(User.apply)
Some notes:
each primitive validation function: nonBlank, nonNegative, getValue returns so called FailFast type, which is monadic, not applicative.
There are 2 functions readName and readAge, which use a composition of the previous ones, and also are FailFast by the nature.
The readUser is on the contrary, fail slow. To achieve it results of readName and readAge are converted to Validated and composed through so called "Syntax"
Let's assume I have another function for validation, that accepts name and age, validated by readName and readAge. For intstance:
//fake implementation:
def validBoth(name:String, age:Int):FailSlow[User] =
Validated.valid[List[String], User](User(name,age))
How to compose validBoth with readName and readAge? With fail fast it is quite simple, cause I use for-comrehension and have access to the results of readName and readAge:
for {
n <- readName...
i <- readAge...
t <- validBoth(n,i)
} yield t
but how to get the same result for failslow?
EDIT probably it is not clear enough, with these function. Here is a real use case. There is a function, similar to readName/readAge that validates date in the similar way. I want to create a validation fucntion, that accepts 2 dates, to make sure that one date comes after another. Date comes from String. Here is an example, how it will look like for FailFast, which is not the best option in this context:
def oneAfterAnother(dateBefore:Date, dateAfter:Date): FailFast[Tuple2[Date,Date]] =
Right((dateBefore, dateAfter))
.ensure(List(s"$dateAfter date cannot be before $dateBefore"))(t => t._1.before(t._2))
for {
dateBefore <- readDate...
dateAfter <- readDate...
t <- oneDateAfterAnother(dateBefore,dateAfter)
} yield t
My purpose is to accumulate possible errors with dates in applicative way.
In the book it is said, p. 157:
We can’t flatMap because Validated isn’t a monad. However, Cats does
provide a stand-in for flatMap called andThen . The type signature of
andThen is identical to that of flatMap, but it has a different name
because it is not a lawful implementation with respect to the monad
laws:
32.valid.andThen { a =>
10.valid.map { b =>
a + b
}
}
Ok, I tried to reuse this solution, based on andThen, but the result had monadic, but not applicative effect:
def oneDateAfterAnotherFailSlow(dateBefore:String, dateAfter:String)
(map: Map[String, String])(format: SimpleDateFormat)
: FailSlow[Tuple2[Date, Date]] =
readDate(dateBefore)(map)(format).toValidated.andThen { before =>
readDate(dateAfter)(map)(format).toValidated.andThen { after =>
oneAfterAnother(before,after).toValidated
}
}
I could compose it finally with the following code:
import cats.syntax.either._
import cats.instances.list._ // for Semigroupal
def oneDateAfterAnotherFailSlow(dateBefore:String, dateAfter:String)
(map: Map[String, String])(format: SimpleDateFormat)
: FailFast[Tuple2[Date, Date]] =
for {
t <-Semigroupal[FailSlow].product(
readDate(dateBefore)(map)(format).toValidated,
readDate(dateAfter)(map)(format).toValidated
).toEither
r <- oneAfterAnother(t._1, t._2)
} yield r
The idea, is that first validations for strings are applied, to make sure dates are correct. They are accumulated with Validated(FailSlow). Then fail-fast is used, cause if any of the dates is wrong and cannot be parsed, it makes no sense to continue and to compare them as dates.
It passed through my test cases.
If you can offer another, more elegant solution, always welcome!
Maybe the code is self-explanatory here:
/** Edited for the new question. */
import cats.data.Validated
import cats.instances.list._ // for Semigroup
import cats.syntax.apply._ // for tupled
import cats.syntax.either._ // for toValidated
type FailFast[A] = Either[List[String], A]
type FailSlow[A] = Validated[List[String], A]
type Date = ???
type SimpleDateFormat = ???
def readDate(date: String)
(map: Map[String, String])
(format: SimpleDateFormat): FailFast[Date] = ???
def oneDateAfterAnotherFailSlow(dateBefore: String, dateAfter: String)
(map: Map[String, String])
(format: SimpleDateFormat): FailSlow[(Date, Date)] =
(
readDate(dateBefore)(map)(format).toValidated,
readDate(dateAfter)(map)(format).toValidated
).tupled.ensure(List(s"$dateAfter date cannot be before $dateBefore"))(t => t._1.before(t._2))
The thing with Applicatives is that you should not (and if working with the abastraction can not) use flatMap since that will have sequential semantics (In this case FailFast behavior).
Thus, you need to use the abstractions that they provide, usually mapN to call a function with all the arguments if all of they are valid or tupled to create a tuple.
Edit
As the documentation states andThen should be used where you want your Validated to work as a Monad without being one.
It is there just by convenience, but you should not used it if you want the FailSlow semantics.
"This function is similar to flatMap on Either. It's not called flatMap, because by Cats convention, flatMap is a monadic bind that is consistent with ap. This method is not consistent with ap (or other Apply-based methods), because it has "fail-fast" behavior as opposed to accumulating validation failures".
I have a sequence of Errors or Views (Seq[Xor[Error,View]])
I want to map this to an Xor of the first error (if any) or a Sequence of Views
(Xor[Error, Seq[View]]) or possibly simply (Xor[Seq[Error],Seq[View])
How can I do this?
You can use sequenceU provided by the bitraverse syntax, similar to as you would do with scalaz. It doesn't seem like the proper type classes exist for Seq though, but you can use List.
import cats._, data._, implicits._, syntax.bitraverse._
case class Error(msg: String)
case class View(content: String)
val errors: List[Xor[Error, View]] = List(
Xor.Right(View("abc")), Xor.Left(Error("error!")),
Xor.Right(View("xyz"))
)
val successes: List[Xor[Error, View]] = List(
Xor.Right(View("abc")),
Xor.Right(View("xyz"))
)
scala> errors.sequenceU
res1: cats.data.Xor[Error,List[View]] = Left(Error(error!))
scala> successes.sequenceU
res2: cats.data.Xor[Error,List[View]] = Right(List(View(abc), View(xyz)))
In the most recent version of Cats Xor is removed and now the standard Scala Either data type is used.
Michael Zajac showed correctly that you can use sequence or sequenceU (which is actually defined on Traverse not Bitraverse) to get an Either[Error, List[View]].
import cats.implicits._
val xs: List[Either[Error, View]] = ???
val errorOrViews: Either[Error, List[View]] = xs.sequenceU
You might want to look at traverse (which is like a map and a sequence), which you can use most of the time instead of sequence.
If you want all failing errors, you cannot use Either, but you can use Validated (or ValidatedNel, which is just a type alias for Validated[NonEmptyList[A], B].
import cats.data.{NonEmptyList, ValidatedNel}
val errorsOrViews: ValidatedNel[Error, List[View]] = xs.traverseU(_.toValidatedNel)
val errorsOrViews2: Either[NonEmptyList[Error], List[View]] = errorsOrViews.toEither
You could also get the errors and the views by using MonadCombine.separate :
val errorsAndViews: (List[Error], List[View]) = xs.separate
You can find more examples and information on Either and Validated on the Cats website.
This question is related to this one, where I was trying to understand how to use the reader monad in Scala.
In the answer the autor uses the following code for getting an instance of ReaderInt[String]:
import scalaz.syntax.applicative._
val alwaysHello2: ReaderInt[String] = "hello".point[ReaderInt]
Which mechanisms does Scala use to resolve the type of the expression "hello".point[ReaderInt] so that it uses the right point function?
A good first step any time you're trying to figure out something like this is to use the reflection API to desugar the expression:
scala> import scalaz.Reader, scalaz.syntax.applicative._
import scalaz.Reader
import scalaz.syntax.applicative._
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> type ReaderInt[A] = Reader[Int, A]
defined type alias ReaderInt
scala> showCode(reify("hello".point[ReaderInt]).tree)
res0: String = `package`.applicative.ApplicativeIdV("hello").point[$read.ReaderInt](Kleisli.kleisliIdMonadReader)
(You generally don't want to use scala.reflect.runtime in real code, but it's extremely handy for investigations like this.)
When the compiler sees you trying to call .point[ReaderInt] on a type that doesn't have a point method—in this case String—it starts looking for implicit conversions that would convert a String into a type that does have a matching point method (this is called "enrichment" in Scala). We can see from the output of showCode that the implicit conversion it finds is a method called ApplicativeIdV in the applicative syntax object.
It then applies this conversion to the String, resulting in a value of type ApplicativeIdV[String]. This type's point method looks like this:
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
Which is syntactic sugar for something like this:
def point[F[_]](implicit F: Applicative[F]): F[A] = F.point(self)
So the next thing it needs to do is find an Applicative instance for F. In your case you've explicitly specified that F is ReaderInt. It resolves the alias to Reader[Int, _], which is itself an alias for Kleisli[Id.Id, Int, _], and starts looking for an instance.
One of the first places it looks will be the Kleisli companion object, since it wants an implicit value of a type that includes Kleisli, and in fact showCode tells us that the one it finds is Kleisli.kleisliIdMonadReader. At that point it's done, and we get the ReaderInt[String] we wanted.
I wanted to update the former answer, but since you created separate question, I put it here.
scalaz.syntax
Let's consider the point example, and you can apply the same reasoning for other methods.
point (or haskell's return) or pure(just a type alias) belongs to Applicative trait. If you want to put something inside some F, you need at least Applicative instance for this F.
Usually, you will provide it implicitly with imports, but you can specify it explicitly as well.
In example from the first question, I assigned it to val
implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]
because scala was not able to figure out the corresponding Int type for this applicative. In other words, it did not know Applicative for which Reader to bring in. (though sometimes compiler can figure it out)
For the Applicatives with one type parameter, we can bring implicit instances in just by using import
import scalaz.std.option.optionInstance
import scalaz.std.list.listInstance
etc...
Okay, you have the instance. Now you need to invoke point on it.
You have few options:
1. Access method directly:
scalaz.std.option.optionInstance.point("hello")
KA.pure("hello")
2. Explicitly pull it from implicit context:
Applicative[Option].point("hello")
If you look into Applicative object, you would see
object Applicative {
#inline def apply[F[_]](implicit F: Applicative[F]): Applicative[F] = F
}
Implementation of apply, is only returning the corresponding Applicative[F] instance for some type F.
So Applicative[Option].point("hello") is converted to
Applicative[Option].apply(scalaz.std.option.optionInstance)
which in the end is just optionInstance
3. Use syntax
import scalaz.syntax.applicative._
brings this method into implicit scope:
implicit def ApplicativeIdV[A](v: => A) = new ApplicativeIdV[A] {
val nv = Need(v)
def self = nv.value
}
trait ApplicativeIdV[A] extends Ops[A] {
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
def pure[F[_] : Applicative]: F[A] = Applicative[F].point(self)
def η[F[_] : Applicative]: F[A] = Applicative[F].point(self)
} ////
So then, whenever you try to invoke point on a String
"hello".point[Option]
compiler realizes, that String does not have the method point and begins to look through implicits, how it can get something which has point, from String.
It finds, that it can convert String to ApplicativeIdV[String], which indeed has method point:
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
So in the end - your call desugares to
new ApplicativeIdV[Option]("hello")
More or less all typeclasses in scalaz are working the same way.
For sequence, the implementation is
def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] =
traverse(fga)(ga => ga)
This colon after G means, that Applicative[G] should be provided implicitly.
It is essentialy the same as:
def sequence[G[_], A](fga: F[G[A]])(implicit ev: Applicative[G[_]]): G[F[A]] =
traverse(fga)(ga => ga)
So all you need is the Applicative[G], and Traverse[F].
import scalaz.std.list.listInstance
import scalaz.std.option.optionInstance
Traverse[List].sequence[Option, String](Option("hello"))
I'm trying to generalize setting up Squeryl (Slick poses the same problems AFAIK). I want to avoid having to name every case class explicitly for a number of general methods.
table[Person]
table[Bookmark]
etc.
This also goes for generating indexes, and creating wrapper methods around the CRUD methods for every case class.
So ideally what I want to do is have a list of classes and make them into tables, add indexes and add a wrapper method:
val listOfClasses = List(classOf[Person], classOf[Bookmark])
listOfClasses.foreach(clazz => {
val tbl = table[clazz]
tbl.id is indexed
etc.
})
I thought Scala Macros would be the thing to apply here, since I don't think you can have values as type parameters. Also I need to generate methods for every type of the form:
def insert(model: Person): Person = persons.insert(model)
I've got my mits on an example on Macros but I don't know how to generate a generic datastructure.
I got this simple example to illustrate what I want:
def makeList_impl(c: Context)(clazz: c.Expr[Class[_]]): c.Expr[Unit] = {
import c.universe._
reify {
println(List[clazz.splice]()) // ERROR: error: type splice is not a member of c.Expr[Class[_]]
}
}
def makeList(clazz: Class[_]): Unit = macro makeList_impl
How do I do this? Or is Scala Macros the wrong tool?
Unfortunately, reify is not flexible enough for your use case, but there's good news. In macro paradise (and most likely in 2.11.0) we have a better tool to construct trees, called quasiquotes: http://docs.scala-lang.org/overviews/macros/quasiquotes.html.
scala> def makeList_impl(c: Context)(clazz: c.Expr[Class[_]]): c.Expr[Any] = {
| import c.universe._
| val ConstantType(Constant(tpe: Type)) = clazz.tree.tpe
| c.Expr[Any](q"List[$tpe]()")
| }
makeList_impl: (c: scala.reflect.macros.Context)(clazz: c.Expr[Class[_]])c.Expr[Any]
scala> def makeList(clazz: Class[_]): Any = macro makeList_impl
defined term macro makeList: (clazz: Class[_])Any
scala> makeList(classOf[Int])
res2: List[Int] = List()
scala> makeList(classOf[String])
res3: List[String] = List()
Quasiquotes are even available in 2.10.x with a minor tweak to the build process (http://docs.scala-lang.org/overviews/macros/paradise.html#macro_paradise_for_210x), so you might want to give them a try.
This will probably not fill all your needs here, but it may help a bit:
The signature of table method looks like this:
protected def table[T]()(implicit manifestT: Manifest[T]): Table[T]
As you can see, it takes implicit Manifest object. That object is passed automatically by the compiler and contains information about type T. This is actually what Squeryl uses to inspect database entity type.
You can just pass these manifests explicitly like this:
val listOfManifests = List(manifest[Person], manifest[Bookmark])
listOfManifests.foreach(manifest => {
val tbl = table()(manifest)
tbl.id is indexed
etc.
})
Unfortunately tbl in this code will have type similar to Table[_ <: CommonSupertypeOfAllGivenEntities] which means that all operations on it must be agnostic of concrete type of database entity.