I am trying to use parMapN function and I am not able to compile the code. If my type is IO then there is not problem, but when I use types on my functions, then I cannot manage to make it work.
In the snippet below, there is randomMessage which compiles and runs correctly but calling to randomMessageF does not compiles since there is not a NonEmptyParallel implicit on the scope. But then, which implicit is using randomMessage? Passing contextShift doest not work either.
import cats.NonEmptyParallel
import cats.effect._
import cats.syntax.all._
import fs2._
import scala.util.Random
object Test extends IOApp {
def randomMessageF[F[_], A, B, C](toA: => F[A],
toB: => F[B],
toC: (A, B) => C)(implicit nep: NonEmptyParallel[F, F]): Stream[F, C] = Stream.eval {
val funcA = toA
val funcB = toB
(funcA, funcB).parMapN {
case (a, b) =>
toC(a, b)
}
}
def randomMessage[A, B, C](toA: => IO[A],
toB: => IO[B],
toC: (A, B) => C): Stream[IO, C] = Stream.eval {
val funcA = toA
val funcB = toB
(funcA, funcB).parMapN {
case (a, b) =>
toC(a, b)
}
}
def run(args: List[String]): IO[ExitCode] = {
println(
randomMessage(
IO(Random.nextInt(1000).toString),
IO(Random.nextString(10)),
(k: String, v: String) => s"$k:$v"
).compile.toList.unsafeRunSync().head)
println(
randomMessageF[IO, String, String, String](
IO(Random.nextInt(1000).toString),
IO(Random.nextString(10)),
(k, v) => s"$k:$v"
)(???).compile.toList.unsafeRunSync().head)
IO(ExitCode(0))
}
}
Try
def randomMessageF[M[_], F[_], A, B, C](toA: => M[A],
toB: => M[B],
toC: (A, B) => C)(implicit
nep: NonEmptyParallel[M, F]): Stream[M, C] = Stream.eval {
val funcA = toA
val funcB = toB
(funcA, funcB).parMapN {
case (a, b) =>
toC(a, b)
}
}
println(
randomMessageF/*[IO, IO.Par, String, String, String]*/(
IO(Random.nextInt(1000).toString),
IO(Random.nextString(10)),
(k: String, v: String) => s"$k:$v"
).compile.toList.unsafeRunSync().head)
In randomMessage the implicit used is NonEmptyParallel[IO, IO.Par].
https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/IO.scala#L834
Related
I'd like to migrate the following code from Scala 2.12 to 2.13
Given any collection of tuples Coll[(A, B)] and a method f: B => IterableOnce[C], I'd like to produce a Coll[(A, C)] by applying f on the second element of the tuple.
implicit class TuplesOps[A, B, Repr <: Traversable[(A, B)]](val s: TraversableLike[(A, B), Repr]) extends AnyVal {
def flatMapValues[C, That](f: B => TraversableOnce[C])(implicit bf: CanBuildFrom[Repr, (A, C), That]) =
s.flatMap { case (a, b) => f(b).map((a, _))}
}
I know that the collection API has changed in 2.13 and I read : https://docs.scala-lang.org/overviews/core/custom-collection-operations.html
I've tried 2 implementations
First
import scala.collection.{ AbstractView, BuildFrom }
import scala.collection.generic.IsSeq
object Evidence extends App {
class TuplesOps[Repr, S <: IsSeq[Repr]](coll: Repr, seq: S) {
def flatMapValues[B, C, D, That](f: C => IterableOnce[D])(implicit bf: BuildFrom[Repr, (B, D), That], ev: seq.A =:= (B, C)): That = {
val seqOps = seq(coll)
bf.fromSpecific(coll)(new AbstractView[(B, D)] {
override def iterator: Iterator[(B, D)] = {
seqOps.flatMap { x => f(ev(x)._2).map((ev(x)._1, _))}.iterator
}
})
}
}
implicit def TuplesOps[Repr](coll: Repr)(implicit seq: IsSeq[Repr]): TuplesOps[Repr, seq.type] =
new TuplesOps(coll, seq)
List("a"->1, "b"->2).flatMapValues{(x:Int) => Seq.fill(x)("x")}
}
And I have this compilation error :
[error] /home/yamo/projects/perso/coll213/src/main/scala/example/Evidence.scala:22:37: diverging implicit expansion for type scala.collection.BuildFrom[List[(String, Int)],(B, String),That]
[error] starting with method Tuple9 in object Ordering
[error] List("a"->1, "b"->2).flatMapValues{(x:Int) => Seq.fill(x)("x")}
Second
import scala.collection.{ AbstractView, BuildFrom }
import scala.collection.generic.IsSeq
object Aux extends App {
type Aux[Repr, B, C] = IsSeq[Repr] { type A = (B, C)}
class TuplesOps[Repr, B, C, S <: Aux[Repr, B, C]](coll: Repr, seq: S) {
def flatMapValues[D, That](f: C => IterableOnce[D])(implicit bf: BuildFrom[Repr, (B, D), That]): That = {
val seqOps = seq(coll)
bf.fromSpecific(coll)(new AbstractView[(B, D)] {
// same as before
override def iterator: Iterator[(B, D)] = {
seqOps.flatMap { case (b, c) => f(c).map((b, _))}.iterator
}
})
}
}
implicit def TuplesOps[Repr, B, C](coll: Repr)(implicit seq: Aux[Repr, B, C]): TuplesOps[Repr, B, C, seq.type] =
new TuplesOps(coll, seq)
List("a"->1, "b"->2).flatMapValues(Seq.fill(_)("x"))
}
And I have this compilation error
[error] /home/yamo/projects/perso/coll213/src/main/scala/example/Aux.scala:24:24: value flatMapValues is not a member of List[(String, Int)]
[error] List("a"->1, "b"->2).flatMapValues(Seq.fill(_)("x"))
Could you help me to make both solution work, if possible ?
I agree, the Custom Collection instructions aren't what they should be.
I find the Factory method a bit easier than the BuildFrom, but I'm still getting used to either/both of them.
import scala.collection.Factory
implicit
class TuplesOps[A,B,CC[x] <: Iterable[x]](val ts: CC[(A,B)]) {
def flatMapValues[C](f: B => IterableOnce[C]
)(implicit fac: Factory[(A,C), CC[(A,C)]]
): CC[(A,C)] =
ts.flatMap{case (a,b) => f(b).iterator.map(x => (a,x))}
.to[CC[(A,C)]](fac)
}
This passes all my simple (minded) tests. It won't work on an Array or an Iterator but then your original Scala 2.12.x version didn't either (for me) so I figured that was okay.
Note - the operation described below now exists in the standard library as partitionMap but I believe it's still a valid question as to how to achieve more general ends
Question regarding scala 2.13 - how do I consume/construct collections of specific types when adding custom collections operations where I need to restrict the element types of the input collections? e.g. how do I define:
def split[CC[_], A, B](coll: CC[Either[A, B]]): (CC[A], CC[B])
Following the documentation I've managed to achieve this as follows:
import collection.generic.IsIterable
import scala.collection.{BuildFrom, Factory}
class SplitOperation[Repr, S <: IsIterable[Repr]](coll: Repr, itr: S) {
def split[A, B, AS, BS](
implicit bfa: BuildFrom[Repr, A, AS],
bfb: BuildFrom[Repr, B, BS],
ev: itr.A =:= Either[A, B]): (AS, BS) = {
val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })
(as, bs)
}
}
implicit def SplitOperation[Repr](coll: Repr)(implicit itr: IsIterable[Repr]): SplitOperation[Repr, itr.type] =
new SplitOperation(coll, itr)
However, I need to supply types at the use-site otherwise I get diverging implicit expansion.
scala> List(Left("bah"), Right(1), Left("gah"), Right(2), Right(3))
res1: List[scala.util.Either[String,Int]] = List(Left(bah), Right(1), Left(gah), Right(2), Right(3))
scala> res1.split
^
error: diverging implicit expansion for type scala.collection.BuildFrom[List[scala.util.Either[String,Int]],A,AS]
But the following works:
scala> res1.split[String, Int, List[String], List[Int]]
res4: (List[String], List[Int]) = (List(bah, gah),List(1, 2, 3))
EDIT
class SplitOperation[X, CC[_], S <: IsIterable[CC[X]]](coll: CC[X], itr: S) {
def split[A, B](implicit bfa: BuildFrom[CC[X], A, CC[A]], bfb: BuildFrom[CC[X], B, CC[B]], ev: itr.A =:= Either[A, B]): (CC[A], CC[B]) = {
val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })
(as, bs)
}
}
implicit def SplitOperation[A, B, CC[_]](coll: CC[Either[A, B]])(implicit itr: IsIterable[CC[Either[A, B]]]): SplitOperation[Either[A, B], CC, itr.type] =
new SplitOperation(coll, itr)
Gives me a slight improvement. Now I only need to provide type parameters A and B at the call site:
scala> l.split[String, Int]
res2: (List[String], List[Int]) = (List(bah, gah),List(1, 2))
This seems to work:
class SplitOperation[A, B, CC[_], S <: IsIterable[CC[Either[A, B]]]](coll: CC[Either[A, B]], itr: S) {
def split(implicit bfa: BuildFrom[CC[Either[A, B]], A, CC[A]], bfb: BuildFrom[CC[Either[A, B]], B, CC[B]], ev: itr.A =:= Either[A, B]): (CC[A], CC[B]) = {
val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })
(as, bs)
}
}
implicit def SplitOperation[A, B, CC[_]](coll: CC[Either[A, B]])(implicit itr: IsIterable[CC[Either[A, B]]]): SplitOperation[A, B, CC, itr.type] =
new SplitOperation(coll, itr)
In your case you don’t want to abstract over the “kind” of the collection type constructor (CC[_] vs CC[_, _], etc.), you always use the CC[_] kind, so you don’t need to use IsIterable.
I think it is also not necessary to support “Sorted” collections (eg, SortedSet) because there is no Ordering instance for Either, so you don’t need to use BuildFrom.
implicit class SplitOperation[A, B, CC[X] <: IterableOps[X, CC, CC[X]]](coll: CC[Either[A, B]]) {
def split: (CC[A], CC[B]) = {
val as = coll.iterableFactory.from(coll.iterator.collect { case Left(a) => a })
val bs = coll.iterableFactory.from(coll.iterator.collect { case Right(b) => b })
(as, bs)
}
}
https://scastie.scala-lang.org/64QxHwteQN2i3udSxCa3yw
I would like to "compose" two monoids using cats. If there exists a defined Monoid[(A, A) => Int], then I would like to be able to create a Monoid[Preference[A]] using the combine and empty methods of the Monoid[(A, A) => Int]. I am using the term "composing" loosely here because I am not sure that the transform I want to do is accurately called composition.
Here is my current attempt...
import cats._
import cats.implicits._
trait Preference[A] extends Order[A]
object Preference {
def from[A](f: (A, A) => Int): Preference[A] = {
new Preference[A] {
def compare(a1: A, a2: A): Int = {
f(a1, a2)
}
}
}
def monoid[A](implicit ev: Monoid[(A, A) => Int]): Monoid[Preference[A]] = {
new Monoid[Preference[A]] {
def combine(p1: Preference[A], p2: Preference[A]): Preference[A] = {
new Preference[A] {
def compare(a1: A, a2:A): Int = {
ev.combine(p1.compare, p2.compare)(a1, a2)
}
}
}
def empty: Preference[A] = {
from(ev.empty)
}
}
}
}
...this compiles but I would like to know if there is a more idiomatic solution available using cats.
Seems like it should be possible to somehow compose the Monoid[(A,A) => Int] with the from combinator that takes a f:(A, A) => Int and returns a Preference[A] to create a Monoid[Preference[A]] but I can not figure out how to do it.
I have seen this SO post which discusses composing monoids using a product combinator which is not what I want.
I'm not aware of anything built-in into cats directly.
It seems that you have an isomorphism between Preference[A] and (A, A) => Int, and you simply want to transfer the monoid-structure from (A, A) => Int to Preference[A]. This can be expressed generically for arbitrary types A and B:
def fromIsomorphicMonoid[A, B](
forward: A => B,
inverse: B => A
)(implicit aMon: Monoid[A]): Monoid[B] = new Monoid[B] {
def combine(b1: B, b2: B): B =
forward(aMon.combine(inverse(b1), inverse(b2)))
def empty: B = forward(aMon.empty)
}
With this helper method, your monoid in Preference becomes just:
def monoid[A](implicit ev: Monoid[(A, A) => Int]): Monoid[Preference[A]] =
fromIsomorphicMonoid(
from,
(p: Preference[A]) => (x:A, y:A) => p.compare(x, y)
)
Full compilable example (without any dependencies):
trait Monoid[X] {
def empty: X
def combine(x: X, y: X): X
}
trait Order[A] {
def compare(a1: A, a2: A): Int
}
def fromIsomorphicMonoid[A, B](
forward: A => B,
inverse: B => A
)(implicit aMon: Monoid[A]): Monoid[B] = new Monoid[B] {
def combine(b1: B, b2: B): B =
forward(aMon.combine(inverse(b1), inverse(b2)))
def empty: B = forward(aMon.empty)
}
trait Preference[A] extends Order[A]
object Preference {
def from[A](f: (A, A) => Int): Preference[A] = {
new Preference[A] {
def compare(a1: A, a2: A): Int = {
f(a1, a2)
}
}
}
def monoid[A](implicit ev: Monoid[(A, A) => Int])
: Monoid[Preference[A]] = fromIsomorphicMonoid(
from,
(p: Preference[A]) => (x:A, y:A) => p.compare(x, y)
)
}
This is a followup to my previous question with an example found on the Internet.
Suppose I define a typeclass Applicative as follows:
trait Functor[T[_]]{
def map[A,B](f:A=>B, ta:T[A]):T[B]
}
trait Applicative[T[_]] extends Functor[T] {
def unit[A](a:A):T[A]
def ap[A,B](tf:T[A=>B], ta:T[A]):T[B]
}
I can define an instance of Applicative for List
object AppList extends Applicative[List] {
def map[A,B](f:A=>B, as:List[A]) = as.map(f)
def unit[A](a: A) = List(a)
def ap[A,B](fs:List[A=>B], as:List[A]) = for(f <- fs; a <- as) yield f(a)
}
For convenience I can define an implicit conversion to add a method <*> to List[A=>B]
implicit def toApplicative[A, B](fs: List[A=>B]) = new {
def <*>(as: List[A]) = AppList.ap(fs, as)
}
Now I can do a cool thing !
zip two lists List[String] and apply f2 to every pair in applicative style
val f2: (String, String) => String = {(first, last) => s"$first $last"}
val firsts = List("a", "b", "c")
val lasts = List("x", "y", "z")
scala> AppList.unit(f2.curried) <*> firsts <*> lasts
res31: List[String] = List(a x, a y, a z, b x, b y, b z, c x, c y, c z)
So far, so good but now I have:
val firstsOpt = Some(firsts)
val lastsOpt = Some(lasts)
I would like to zip firsts and lasts, apply f2, and get Option[List[String]] in applicative style. In other words I need <*> for Option[List[_]]. How can I do it ?
Firstly, you need an instance of applicative for Option:
implicit object AppOption extends Applicative[Option] {
def map[A, B](f: A => B, o: Option[A]) = o.map(f)
def unit[A](a: A): Option[A] = Some(a)
def ap[A, B](of: Option[A => B], oa: Option[A]) = of match {
case Some(f) => oa.map(f)
case None => None
}
}
Then you can also create an applicative instance for the composition of two applicatives (note, based on the Haskell version):
class AppComp[F[_], G[_]](fa: Applicative[F], ga: Applicative[G]) extends Applicative[({ type f[A] = F[G[A]]})#f] {
def map[A, B](f: A => B, a: F[G[A]]): F[G[B]] = fa.map((g: G[A]) => ga.map(f, g), a)
def unit[A](a: A) = fa.unit(ga.unit(a))
def ap[A, B](f: F[G[A => B]], a: F[G[A]]): F[G[B]] = {
val liftg: G[A => B] => (G[A] => G[B]) = gf => (gx => ga.ap(gf, gx))
val ffg: F[G[A] => G[B]] = fa.map(liftg, f)
fa.ap(ffg, a)
}
}
implicit def toComp[F[_], G[_]](implicit fa: Applicative[F], ga: Applicative[G]) = new AppComp[F, G](fa, ga)
Finally you can now do:
val ola = toComp[Option, List]
ola.ap(ola.ap(ola.unit(f2.curried), firstsOpt), lastsOpt)
You could probably also remove some of the noise by generalising <*> to work for any applicative.
What is the best way to partition Seq[A \/ B] into (Seq[A], Seq[B]) using Scalaz?
There is a method: separate defined in MonadPlus. This typeclass is a combination a Monad with PlusEmpty (generalized Monoid). So you need to define instance for Seq:
1) MonadPlus[Seq]
implicit val seqmp = new MonadPlus[Seq] {
def plus[A](a: Seq[A], b: => Seq[A]): Seq[A] = a ++ b
def empty[A]: Seq[A] = Seq.empty[A]
def point[A](a: => A): Seq[A] = Seq(a)
def bind[A, B](fa: Seq[A])(f: (A) => Seq[B]): Seq[B] = fa.flatMap(f)
}
Seq is already monadic, so point and bind are easy, empty and plus are monoid operations and Seq is a free monoid
2) Bifoldable[\/]
implicit val bife = new Bifoldable[\/] {
def bifoldMap[A, B, M](fa: \/[A, B])(f: (A) => M)(g: (B) => M)(implicit F: Monoid[M]): M = fa match {
case \/-(r) => g(r)
case -\/(l) => f(l)
}
def bifoldRight[A, B, C](fa: \/[A, B], z: => C)(f: (A, => C) => C)(g: (B, => C) => C): C = fa match {
case \/-(r) => g(r, z)
case -\/(l) => f(l, z)
}
}
Also easy, standard folding, but for type constructors with two parameters.
Now you can use separate:
val seq: Seq[String \/ Int] = List(\/-(10), -\/("wrong"), \/-(22), \/-(1), -\/("exception"))
scala> seq.separate
res2: (Seq[String], Seq[Int]) = (List(wrong, number exception),List(10, 22, 1))
Update
Thanks to Kenji Yoshida, there is a Bitraverse[\/], so you need only MonadPlus.
And a simple solution using foldLeft:
seq.foldLeft((Seq.empty[String], Seq.empty[Int])){ case ((as, ai), either) =>
either match {
case \/-(r) => (as, ai :+ r)
case -\/(l) => (as :+ l, ai)
}
}