I'm looking for a short way to traverse and reduce at the same time. Here is the solution I came up with:
import cats.{Applicative, Monad}
import cats.instances.list._
import cats.syntax.functor._
import cats.syntax.flatMap._
import cats.syntax.traverse._
object Test extends App {
def intFM[F[_], M[_]](i: Int): F[M[Int]] = ???
def traverseReduce[F[_]: Applicative, M[_]: Monad](lst: List[Int]) =
lst.traverse(intFM[F, M]).map(_.reduce(_ >> _))
}
As can be seen I did 3 operations: traverse, map and reduce, but I expected that it was possible to do the reduction while traversing. Is there some shorthand?
You can try without traversing
def traverseReduce[F[_]: Applicative, M[_]: Monad](lst: List[Int]): F[M[Int]] =
lst.map(intFM[F, M]).reduce((_, _).mapN(_ >> _))
Related
I have a value of this type:
val effects : List[EitherT[Future, Error, Foo]] = ...
How do I run through the list and execute those effects? I did
effects.traverse
But that method is not defined for that type.
As mentioned in comments, it's better to get rid of Future when you are declaring some list of effects and want to execute them and gather effects in one list after. It's better to use IO or another lazy evaluated effect.
So, if you just need to traverse on Future[List[A]]:
import cats.data.EitherT
import scala.concurrent.{ExecutionContext, Future}
import cats.syntax.traverse._
import cats.instances.list._
import cats.instances.future._
implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.global
case class Foo()
val effects : List[EitherT[Future, Error, Foo]] = ???
def f(e: EitherT[Future, Error, Foo]): Future[Either[Error, Foo]] = ???
val result: Future[List[Either[Error, Foo]]] = effects.traverse(f)
this code compiles and all you need is implement f. You need to add import cats.instances.future._ to have traverse function in Furure.
but better way to construct you process on something like IO:
import cats.data.EitherT
import cats.syntax.traverse._
import cats.instances.list._
import cats.effect.IO
val effects : List[EitherT[IO, Error, Foo]] = ???
def f(e: EitherT[IO, Error, Foo]): IO[Either[Error, Foo]] = ???
val result: IO[List[Either[Error, Foo]]] = effects.traverse(f)
and call it using unsafeRunAsync.
I have a wrapper trait that extends BasicFormats from spray json https://github.com/spray/spray-json/blob/release/1.3.x/src/main/scala/spray/json/BasicFormats.scala
but I would like to override the behavior of implicit object BigDecimalJsonFormat extends JsonFormat[BigDecimal] to add rounding logic. Example being
import spray.json._
import scala.math.BigDecimal.RoundingMode
case class Foo(i: BigDecimal)
object Foo extends DefaultJsonProtocol {
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] =
new JsonFormat[BigDecimal] {
def write(f: BigDecimal) = JsNumber(f.setScale(2, RoundingMode.HALF_UP))
def read(json: JsValue): BigDecimal =
DefaultJsonProtocol.BigDecimalJsonFormat.read(json)
}
implicit val fooFormatter = jsonFormat1(this.apply)
}
scastie snippet:
https://scastie.scala-lang.org/9RNhajzGRDGMX5QsuAohVA
Great question, I wasn't even aware this may cause so many problems. The solution I am about to propose is probably not the cleanest, but it does the job... First of all, you don't have to extend DefaultJsonProtocol, you might also import it's members:
object Foo {
import DefaultJsonProtocol._
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] = ...
implicit val fooFormatter = jsonFormat1(this.apply)
}
This doesn't solve the problem but that way you can exclude some of the members so that they are not imported. Here's the syntax for that
import DefaultJsonProtocol.{BigDecimalJsonFormat => _, _}
It basically says: don't import BigDecimalJsonFormat but import the rest.
And the following code sums it up.
import spray.json._
import scala.math.BigDecimal.RoundingMode
case class Foo(i: BigDecimal)
object Foo {
import DefaultJsonProtocol.{BigDecimalJsonFormat => _, _}
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] =
new JsonFormat[BigDecimal] {
def write(f: BigDecimal) = JsNumber(f.setScale(2, RoundingMode.HALF_UP))
def read(json: JsValue): BigDecimal =
DefaultJsonProtocol.BigDecimalJsonFormat.read(json)
}
implicit val fooFormatter = jsonFormat1(this.apply)
}
I have a question about using Traverse together with EitherT. Let's say we have a code like this:
def validate(s: String): EitherT[Future, NumberFormatException, Int] = {
EitherT(Future.successful(try { Right(s.toInt) } catch { case e:
NumberFormatException => Left(e)}))
}
List("1", "2").traverse(validate)
Unfortunately this code does not compile, because we are missing something:
error: could not find implicit value for evidence parameter of type cats.Applicative[G] List("1", "2").traverse(validate)
I tried to look this up and found for example this answer: Switching between EitherT and Validation to accumulate error or traverse or Validation versus disjunction
So it seems some solution could exists. But the problem is that both of them are using traverseU, which is no longer an option in scala 2.12. So how can this be done please?
EDIT
This is the code including imports:
import cats.data.EitherT
import cats.syntax.traverse._
import cats.instances.list._
import cats.instances.future._
import scala.concurrent.ExecutionContext.global
import scala.concurrent.Future
def validate(s: String): EitherT[Future, NumberFormatException, Int] = {
EitherT(Future.successful(try { Right(s.toInt) } catch { case e:
NumberFormatException => Left(e)}))
}
List("1", "2").traverse(validate)
Usually cats will pack specific evidence implicits under different imports. In this case, you need the proofs for List and Future.
import cats.data.EitherT
import cats.syntax.traverse._
import cats.instances.list._
import cats.instances.future._
import scala.concurrent.Future
def validate(s: String): EitherT[Future, NumberFormatException, Int] = {
EitherT(Future.successful(try { Right(s.toInt) } catch { case e: NumberFormatException => Left(e) }))
}
List("1", "2").traverse(validate)
This code compiles with cats 1.2.0 for me.
import cats.{Applicative, Monad}
import cats.data.EitherT
import cats.syntax.traverse._
import cats.instances.list._
import cats.instances.future._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
def validate(s: String): EitherT[Future, NumberFormatException, Int] = {
EitherT(Future.successful(try { Right(s.toInt) } catch { case e: NumberFormatException => Left(e) }))
}
type Tmp[T] = EitherT[Future, NumberFormatException,T]
List("1", "2").traverse[Tmp, Int](validate)
So this is how it works to me. I had to create new type.
I'm struggling to write a method that operates on either Free Monad to Tagles Final. I would like to use type class to pass an interpreter that produces a Monad. In the same function I would like to use map function.
I don't know how to express type bound so that the M type is a functor or monad.
import cats._
import cats.free.Free
def eval[M[_]](param: String)(implicit op: Algebra ~> M): M[String] {
val program: Free[Algebra, String] = Free.liftF(Operation(param))
Free.foldMap(op)
}
def process[M[_]](param: String)(implicit op: Algebra ~> M): M[String] {
val result = eval(param)
result.map(_.toUpper) //this doesn't compile because M is missing map method
}
Try
import cats.{Monad, ~>}
import cats.free.Free
import cats.syntax.functor._
import scala.language.higherKinds
trait Algebra[_]
case class Operation(str: String) extends Algebra[String]
def eval[M[_]: Monad](param: String)(implicit op: Algebra ~> M): M[String] = {
val program: Free[Algebra, String] = Free.liftF (Operation (param) )
Free.foldMap(op).apply(program)
}
def process[M[_]: Monad](param: String)(implicit op: Algebra ~> M): M[String] = {
val result = eval(param)
result.map(_.toUpperCase)
}
Is there an easy way to convert a
java.lang.Iterable[_]
to a
Scala.Iterable[_]
?
In Scala 2.8 this became much much easier, and there are two ways to achieve it. One that's sort of explicit (although it uses implicits):
import scala.collection.JavaConverters._
val myJavaIterable = someExpr()
val myScalaIterable = myJavaIterable.asScala
EDIT: Since I wrote this, the Scala community has arrived at a broad consensus that JavaConverters is good, and JavaConversions is bad, because of the potential for spooky-action-at-a-distance. So don't use JavaConversions at all!
And one that's more like an implicit implicit: :)
import scala.collection.JavaConversions._
val myJavaIterable = someExpr()
for (magicValue <- myJavaIterable) yield doStuffWith(magicValue)
Yes use implicit conversions:
import java.lang.{Iterable => JavaItb}
import java.util.{Iterator => JavaItr}
implicit def jitb2sitb[T](jit: JavaItb[T]): Iterable[T] = new SJIterable(jit);
implicit def jitr2sitr[A](jit: JavaItr[A]): Iterator[A] = new SJIterator(jit)
Which can then be easily implemented:
class SJIterable[T](private val jitb: JavaItr[T]) extends Iterable[T] {
def elements(): Iterator[T] = jitb.iterator()
}
class SJIterator[T](private val jit: JavaItr[T]) extends Iterator[T] {
def hasNext: Boolean = jit hasNext
def next: T = jit next
}
Starting Scala 2.13, package scala.jdk.CollectionConverters replaces deprecated packages scala.collection.JavaConverters/JavaConversions:
import scala.jdk.CollectionConverters._
// val javaIterable: java.lang.Iterable[Int] = Iterable(1, 2, 3).asJava
javaIterable.asScala
// Iterable[Int] = List(1, 2, 3)