Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more Parallel instances #1938

Merged
merged 80 commits into from
Nov 18, 2017
Merged
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
eaf34e6
Initial version of Parallel
Aug 21, 2017
21942c5
Add Either/Validated Parallel instance
Aug 21, 2017
b37732b
Break up syntax for parallel
Aug 21, 2017
664988a
Add Parallel syntax tests
Aug 21, 2017
e7f6f68
Add Tuple syntax for Parallel
Aug 22, 2017
f37500a
Add ParallelTests
Aug 22, 2017
447d929
Fix Parallel law
Aug 23, 2017
4259554
Add more tests
Aug 23, 2017
6c5efc9
Add Parallel Kleisli instance
Aug 23, 2017
d7ba338
Add instances for OptionT and EitherT to nested
Aug 23, 2017
a7bea82
Add law tests for parallel OptionT and EitherT
Aug 23, 2017
1556909
Make EitherT instance forward to Validated
Aug 23, 2017
b3470db
Add Kleisli lawTest
Aug 23, 2017
b458b3d
Add WriterT instance
Aug 23, 2017
2815a5b
Add more tests
Aug 24, 2017
7844788
Add scaladoc
Aug 24, 2017
378549f
Add ApplicativeError instance for MonadError and Parallel
Aug 26, 2017
1490fe4
Add Test that actually hits the implicated ApplicativeError instance
Aug 26, 2017
2dc71fe
Fix mixup
Aug 28, 2017
00664ae
Move appError instance to Parallel companion object
Aug 29, 2017
f941a0c
Fix apperror test
Aug 29, 2017
1236205
Add sequential roundtrip law
Aug 30, 2017
17c0bc0
Add ZipNEL and ZipNEV and Parallel instances
Sep 2, 2017
1502087
Add law for testing that pure is consistent across Parallel pairs
Sep 3, 2017
f1b1c1a
Add Parallel Serializable tests
Sep 4, 2017
9252e36
Add EitherT Parallel instance that doesn't require a Parallel Instanc…
Sep 5, 2017
e8eb35d
Add ZipVector + Parallel instance
Sep 7, 2017
1a99aab
Add ZipVector test
Sep 10, 2017
ae03b33
Add scaladoc to ApplicativeError and change order of type parameters
Sep 10, 2017
11caba0
Add Parallel#identity function
Sep 10, 2017
1027a41
Add identity instances for Future and Id
Sep 10, 2017
942a152
Simplify parAp2 implementation
Sep 12, 2017
6354e08
Refactor Parallel
Sep 12, 2017
26b7930
Add applicativeError instace method
Sep 12, 2017
9e3891d
Reverse applicativeError and remove redundant .apply
Sep 15, 2017
4dbc995
Simplify further
Sep 15, 2017
61b7cc7
Add FailFastFuture + Parallel instance
Sep 21, 2017
50c5732
Shorten wait times
Sep 22, 2017
c661860
Add ZipStream and OneAnd instance
Sep 22, 2017
ccc5f45
Convert traits to abstract classes
Sep 22, 2017
3a300b4
Merge branch 'master' into add-parallel-class
Sep 22, 2017
ecc8e50
Add consistency test for zip stream
Sep 22, 2017
4882401
Add Applicative test for Applicative[OneAnd]
Sep 22, 2017
50c9619
Add parAp test
Sep 27, 2017
db973c9
Add ZipList and lawtest all Zip* instances
Sep 28, 2017
615a1a5
Add ZipList consistency test
Sep 28, 2017
7395c0a
Add NonEmptyParallel
Sep 28, 2017
a8afdfe
Add test cases for ParNonEmptyTraverse
Sep 29, 2017
7f91072
Update scaladoc
Sep 29, 2017
c5e3423
Remove FailFastFuture and all Zip* instances
Sep 29, 2017
15d9a45
Rename methods in NonEmptyParallel
Sep 30, 2017
ad8a7c4
optimize AppError
Sep 30, 2017
71a1239
Add parFlatTraverse and sequence
Oct 1, 2017
eb274cf
Revert "Remove FailFastFuture and all Zip* instances"
Sep 29, 2017
4151e7e
Add parFlatTraverse and sequence
Oct 1, 2017
87f7b87
Merge branch 'master' into add-parallel-class
Oct 14, 2017
c956900
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 14, 2017
4a9f2ad
Add isomorphic functor law
Oct 14, 2017
e7f659e
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 14, 2017
17acb6f
Add ZipMap?
Oct 14, 2017
7a6cd52
Fix law test parameters
Oct 14, 2017
c67c953
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 14, 2017
cca85ea
Merge branch 'master' into add-parallel-class
Oct 16, 2017
ddb2457
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 16, 2017
8dcfc4a
Merge branch 'master' into add-parallel-class
Oct 17, 2017
bcad984
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 17, 2017
782d568
Remove ZipMap
Oct 19, 2017
4bbd46e
Merge branch 'master' into add-parallel-class
Oct 17, 2017
0c87a1b
Merge branch 'master' into add-parallel-class
Oct 19, 2017
e9ab6b4
Merge branch 'add-parallel-class' into parallel-zip-instances
Oct 19, 2017
7074f8f
Merge branch 'master' into parallel-zip-instances
Oct 27, 2017
d1eeb55
Fix the priority of OneAnd instances
Oct 31, 2017
9114b2a
Rename Parallel tests
Nov 6, 2017
8bfec4b
Rename Parallel tests
Nov 6, 2017
5f6ef8c
Merge branch 'parallel-zip-instances' of https://github.com/LukaJCB/c…
Nov 10, 2017
6c22f90
Merge branch 'master' into parallel-zip-instances
Nov 10, 2017
0e752e3
Add mima exceptions
Nov 10, 2017
2ca66c9
Remove fail fast future
Nov 14, 2017
c92a34a
Merge branch 'master' into parallel-zip-instances
Nov 14, 2017
15def60
Merge branch 'master' into parallel-zip-instances
Nov 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,21 @@ lazy val binaryCompatibleVersion = "1.0.0-RC1"
def mimaSettings(moduleName: String) = Seq(
mimaPreviousArtifacts := Set("org.typelevel" %% moduleName % binaryCompatibleVersion),
// TODO: remove this post-release of 1.0.0
mimaBinaryIssueFilters += {
mimaBinaryIssueFilters ++= {
import com.typesafe.tools.mima.core._
import com.typesafe.tools.mima.core.ProblemFilters._
exclude[ReversedMissingMethodProblem]("cats.syntax.FoldableSyntax.catsSyntaxFoldOps")
Seq(
exclude[ReversedMissingMethodProblem]("cats.syntax.FoldableSyntax.catsSyntaxFoldOps"),
exclude[MissingTypesProblem]("cats.data.OneAndLowPriority3"),
exclude[MissingTypesProblem]("cats.data.OneAndLowPriority2"),
exclude[MissingTypesProblem]("cats.data.OneAndLowPriority1"),
exclude[DirectMissingMethodProblem]("cats.data.OneAndLowPriority3.catsDataNonEmptyTraverseForOneAnd"),
exclude[DirectMissingMethodProblem]("cats.data.OneAndLowPriority2.catsDataTraverseForOneAnd"),
exclude[ReversedMissingMethodProblem]("cats.instances.ParallelInstances.catsStdNonEmptyParallelForZipVector"),
exclude[ReversedMissingMethodProblem]("cats.instances.ParallelInstances.catsStdParallelForZipStream"),
exclude[ReversedMissingMethodProblem]("cats.instances.ParallelInstances.catsStdNonEmptyParallelForZipList"),
exclude[ReversedMissingMethodProblem]("cats.instances.ParallelInstances.catsStdParallelForFailFastFuture")
)
}
)

Expand Down
36 changes: 36 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyList.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats
package data

import cats.data.NonEmptyList.ZipNonEmptyList
import cats.instances.list._
import cats.syntax.order._
import scala.annotation.tailrec
Expand Down Expand Up @@ -421,6 +422,27 @@ object NonEmptyList extends NonEmptyListInstances {
def fromReducible[F[_], A](fa: F[A])(implicit F: Reducible[F]): NonEmptyList[A] =
F.toNonEmptyList(fa)

class ZipNonEmptyList[A](val value: NonEmptyList[A]) extends AnyVal

object ZipNonEmptyList {

def apply[A](nev: NonEmptyList[A]): ZipNonEmptyList[A] =
new ZipNonEmptyList(nev)

implicit val catsDataCommutativeApplyForZipNonEmptyList: CommutativeApply[ZipNonEmptyList] =
new CommutativeApply[ZipNonEmptyList] {
def ap[A, B](ff: ZipNonEmptyList[A => B])(fa: ZipNonEmptyList[A]): ZipNonEmptyList[B] =
ZipNonEmptyList(ff.value.zipWith(fa.value)(_ apply _))

override def map[A, B](fa: ZipNonEmptyList[A])(f: (A) => B): ZipNonEmptyList[B] =
ZipNonEmptyList(fa.value.map(f))

override def product[A, B](fa: ZipNonEmptyList[A], fb: ZipNonEmptyList[B]): ZipNonEmptyList[(A, B)] =
ZipNonEmptyList(fa.value.zipWith(fb.value){ case (a, b) => (a, b) })
}

implicit def zipNelEq[A: Eq]: Eq[ZipNonEmptyList[A]] = Eq.by(_.value)
}
}

private[data] sealed abstract class NonEmptyListInstances extends NonEmptyListInstances0 {
Expand Down Expand Up @@ -534,6 +556,20 @@ private[data] sealed abstract class NonEmptyListInstances extends NonEmptyListIn
new NonEmptyListOrder[A] {
val A0 = A
}

implicit def catsDataNonEmptyParallelForNonEmptyList[A]: NonEmptyParallel[NonEmptyList, ZipNonEmptyList] =
new NonEmptyParallel[NonEmptyList, ZipNonEmptyList] {

def flatMap: FlatMap[NonEmptyList] = NonEmptyList.catsDataInstancesForNonEmptyList

def apply: Apply[ZipNonEmptyList] = ZipNonEmptyList.catsDataCommutativeApplyForZipNonEmptyList

def sequential: ZipNonEmptyList ~> NonEmptyList =
λ[ZipNonEmptyList ~> NonEmptyList](_.value)

def parallel: NonEmptyList ~> ZipNonEmptyList =
λ[NonEmptyList ~> ZipNonEmptyList](nel => new ZipNonEmptyList(nel))
}
}

private[data] sealed abstract class NonEmptyListInstances0 extends NonEmptyListInstances1 {
Expand Down
33 changes: 33 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyVector.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats
package data

import cats.data.NonEmptyVector.ZipNonEmptyVector
import scala.annotation.tailrec
import scala.collection.immutable.{TreeSet, VectorBuilder}
import cats.instances.vector._
Expand Down Expand Up @@ -350,6 +351,18 @@ private[data] sealed abstract class NonEmptyVectorInstances {
implicit def catsDataSemigroupForNonEmptyVector[A]: Semigroup[NonEmptyVector[A]] =
catsDataInstancesForNonEmptyVector.algebra

implicit def catsDataParallelForNonEmptyVector[A]: NonEmptyParallel[NonEmptyVector, ZipNonEmptyVector] =
new NonEmptyParallel[NonEmptyVector, ZipNonEmptyVector] {

def apply: Apply[ZipNonEmptyVector] = ZipNonEmptyVector.catsDataCommutativeApplyForZipNonEmptyVector
def flatMap: FlatMap[NonEmptyVector] = NonEmptyVector.catsDataInstancesForNonEmptyVector

def sequential: ZipNonEmptyVector ~> NonEmptyVector =
λ[ZipNonEmptyVector ~> NonEmptyVector](_.value)

def parallel: NonEmptyVector ~> ZipNonEmptyVector =
λ[NonEmptyVector ~> ZipNonEmptyVector](nev => new ZipNonEmptyVector(nev))
}

}

Expand All @@ -376,5 +389,25 @@ object NonEmptyVector extends NonEmptyVectorInstances with Serializable {
if (vector.nonEmpty) new NonEmptyVector(vector)
else throw new IllegalArgumentException("Cannot create NonEmptyVector from empty vector")

class ZipNonEmptyVector[A](val value: NonEmptyVector[A]) extends Serializable

object ZipNonEmptyVector {

def apply[A](nev: NonEmptyVector[A]): ZipNonEmptyVector[A] =
new ZipNonEmptyVector(nev)

implicit val catsDataCommutativeApplyForZipNonEmptyVector: CommutativeApply[ZipNonEmptyVector] =
new CommutativeApply[ZipNonEmptyVector] {
def ap[A, B](ff: ZipNonEmptyVector[A => B])(fa: ZipNonEmptyVector[A]): ZipNonEmptyVector[B] =
ZipNonEmptyVector(ff.value.zipWith(fa.value)(_ apply _))

override def map[A, B](fa: ZipNonEmptyVector[A])(f: (A) => B): ZipNonEmptyVector[B] =
ZipNonEmptyVector(fa.value.map(f))

override def product[A, B](fa: ZipNonEmptyVector[A], fb: ZipNonEmptyVector[B]): ZipNonEmptyVector[(A, B)] =
ZipNonEmptyVector(fa.value.zipWith(fb.value){ case (a, b) => (a, b) })
}

implicit def zipNevEq[A: Eq]: Eq[ZipNonEmptyVector[A]] = Eq.by(_.value)
}
}
45 changes: 39 additions & 6 deletions core/src/main/scala/cats/data/OneAnd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,22 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
}


private[data] sealed abstract class OneAndInstances extends OneAndLowPriority3 {
private[data] sealed abstract class OneAndInstances extends OneAndLowPriority0 {

implicit def catsDataParallelForOneAnd[A, M[_] : Alternative, F[_] : Alternative]
(implicit P: Parallel[M, F]): Parallel[OneAnd[M, ?], OneAnd[F, ?]] =
new Parallel[OneAnd[M, ?], OneAnd[F, ?]] {
def monad: Monad[OneAnd[M, ?]] = catsDataMonadForOneAnd(P.monad, Alternative[M])

def applicative: Applicative[OneAnd[F, ?]] = catsDataApplicativeForOneAnd(Alternative[F])

def sequential: OneAnd[F, ?] ~> OneAnd[M, ?] =
λ[OneAnd[F, ?] ~> OneAnd[M, ?]](ofa => OneAnd(ofa.head, P.sequential(ofa.tail)))

def parallel: OneAnd[M, ?] ~> OneAnd[F, ?] =
λ[OneAnd[M, ?] ~> OneAnd[F, ?]](ofa => OneAnd(ofa.head, P.parallel(ofa.tail)))

}

implicit def catsDataEqForOneAnd[A, F[_]](implicit A: Eq[A], FA: Eq[F[A]]): Eq[OneAnd[F, A]] =
new Eq[OneAnd[F, A]]{
Expand Down Expand Up @@ -186,7 +200,7 @@ private[data] sealed abstract class OneAndInstances extends OneAndLowPriority3 {
}
}

private[data] sealed abstract class OneAndLowPriority0 {
private[data] sealed abstract class OneAndLowPriority4 {
implicit val catsDataComonadForNonEmptyStream: Comonad[OneAnd[Stream, ?]] =
new Comonad[OneAnd[Stream, ?]] {
def coflatMap[A, B](fa: OneAnd[Stream, A])(f: OneAnd[Stream, A] => B): OneAnd[Stream, B] = {
Expand All @@ -207,8 +221,7 @@ private[data] sealed abstract class OneAndLowPriority0 {
}
}


private[data] sealed abstract class OneAndLowPriority1 extends OneAndLowPriority0 {
private[data] sealed abstract class OneAndLowPriority3 extends OneAndLowPriority4 {

implicit def catsDataFunctorForOneAnd[F[_]](implicit F: Functor[F]): Functor[OneAnd[F, ?]] =
new Functor[OneAnd[F, ?]] {
Expand All @@ -218,7 +231,27 @@ private[data] sealed abstract class OneAndLowPriority1 extends OneAndLowPriority

}

private[data] sealed abstract class OneAndLowPriority2 extends OneAndLowPriority1 {
private[data] sealed abstract class OneAndLowPriority2 extends OneAndLowPriority3 {

implicit def catsDataApplicativeForOneAnd[F[_]](implicit F: Alternative[F]): Applicative[OneAnd[F, ?]] =
new Applicative[OneAnd[F, ?]] {
override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] =
fa.map(f)

def pure[A](x: A): OneAnd[F, A] =
OneAnd(x, F.empty)

override def ap[A, B](ff: OneAnd[F, A => B])(fa: OneAnd[F, A]): OneAnd[F, B] = {
val (f, tf) = (ff.head, ff.tail)
val (a, ta) = (fa.head, fa.tail)
val fb = F.ap(tf)(F.combineK(F.pure(a), ta))
OneAnd(f(a), F.combineK(F.map(ta)(f), fb))
}
}

}

private[data] sealed abstract class OneAndLowPriority1 extends OneAndLowPriority2 {

implicit def catsDataTraverseForOneAnd[F[_]](implicit F: Traverse[F]): Traverse[OneAnd[F, ?]] =
new Traverse[OneAnd[F, ?]] {
Expand All @@ -237,7 +270,7 @@ private[data] sealed abstract class OneAndLowPriority2 extends OneAndLowPriority
}


private[data] sealed abstract class OneAndLowPriority3 extends OneAndLowPriority2 {
private[data] sealed abstract class OneAndLowPriority0 extends OneAndLowPriority1 {

implicit def catsDataNonEmptyTraverseForOneAnd[F[_]](implicit F: Traverse[F], F2: Alternative[F]): NonEmptyTraverse[OneAnd[F, ?]] =
new NonEmptyReducible[OneAnd[F, ?], F] with NonEmptyTraverse[OneAnd[F, ?]] {
Expand Down
26 changes: 26 additions & 0 deletions core/src/main/scala/cats/data/ZipList.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cats.data

import cats.{CommutativeApply, Eq}
import cats.instances.list.catsKernelStdEqForList

class ZipList[A](val value: List[A]) extends AnyVal

object ZipList {

def apply[A](value: List[A]): ZipList[A] = new ZipList(value)

implicit val catsDataCommutativeApplyForZipList: CommutativeApply[ZipList] = new CommutativeApply[ZipList] {

override def map[A, B](fa: ZipList[A])(f: (A) => B): ZipList[B] =
ZipList(fa.value.map(f))

def ap[A, B](ff: ZipList[A => B])(fa: ZipList[A]): ZipList[B] =
ZipList((ff.value, fa.value).zipped.map(_ apply _))

override def product[A, B](fa: ZipList[A], fb: ZipList[B]): ZipList[(A, B)] =
ZipList(fa.value.zip(fb.value))

}

implicit def catsDataEqForZipList[A: Eq]: Eq[ZipList[A]] = Eq.by(_.value)
}
32 changes: 32 additions & 0 deletions core/src/main/scala/cats/data/ZipStream.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cats.data

import cats.{Alternative, CommutativeApplicative, Eq}
import cats.instances.stream._

class ZipStream[A](val value: Stream[A]) extends AnyVal

object ZipStream {

def apply[A](value: Stream[A]): ZipStream[A] = new ZipStream(value)

implicit val catsDataAlternativeForZipStream: Alternative[ZipStream] with CommutativeApplicative[ZipStream] =
new Alternative[ZipStream] with CommutativeApplicative[ZipStream] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be lawful right? but we can't test it...that's awkward. how about moving it to alleycats?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awkward indeed, I'm not sure if alleycats is the right place, since they can be proven to be lawful in e.g. Haskell, but I agree that it's awkward.

Maybe we should move the CommutativeApplicative instance to Alleycats and keep the CommutativeApply instance here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that but it would cause implicit conflict if you import both right? Unless we do the export hook trick which is kind of deprecated. Maybe we just document a bit more.

def pure[A](x: A): ZipStream[A] = new ZipStream(Stream.continually(x))

override def map[A, B](fa: ZipStream[A])(f: (A) => B): ZipStream[B] =
ZipStream(fa.value.map(f))

def ap[A, B](ff: ZipStream[A => B])(fa: ZipStream[A]): ZipStream[B] =
ZipStream((ff.value, fa.value).zipped.map(_ apply _))

override def product[A, B](fa: ZipStream[A], fb: ZipStream[B]): ZipStream[(A, B)] =
ZipStream(fa.value.zip(fb.value))

def empty[A]: ZipStream[A] = ZipStream(Stream.empty[A])

def combineK[A](x: ZipStream[A], y: ZipStream[A]): ZipStream[A] =
ZipStream(Alternative[Stream].combineK(x.value, y.value))
}

implicit def catsDataEqForZipStream[A: Eq]: Eq[ZipStream[A]] = Eq.by(_.value)
}
22 changes: 22 additions & 0 deletions core/src/main/scala/cats/data/ZipVector.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cats.data

import cats.{CommutativeApply, Eq}
import cats.instances.vector._

class ZipVector[A](val value: Vector[A]) extends AnyVal

object ZipVector {

def apply[A](value: Vector[A]): ZipVector[A] = new ZipVector(value)

implicit val catsDataCommutativeApplyForZipVector: CommutativeApply[ZipVector] = new CommutativeApply[ZipVector] {

override def map[A, B](fa: ZipVector[A])(f: (A) => B): ZipVector[B] =
ZipVector(fa.value.map(f))
def ap[A, B](ff: ZipVector[A => B])(fa: ZipVector[A]): ZipVector[B] =
ZipVector((ff.value, fa.value).zipped.map(_ apply _))

}

implicit def catsDataEqForZipVector[A: Eq]: Eq[ZipVector[A]] = Eq.by(_.value)
}
42 changes: 41 additions & 1 deletion core/src/main/scala/cats/instances/parallel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package cats.instances
import cats.data._
import cats.kernel.Semigroup
import cats.syntax.either._
import cats.{Applicative, Functor, Monad, Parallel, ~>}
import cats.{Applicative, Apply, FlatMap, Functor, Monad, NonEmptyParallel, Parallel, ~>}


trait ParallelInstances extends ParallelInstances1 {
implicit def catsParallelForEitherValidated[E: Semigroup]: Parallel[Either[E, ?], Validated[E, ?]] = new Parallel[Either[E, ?], Validated[E, ?]] {
Expand Down Expand Up @@ -36,6 +37,45 @@ trait ParallelInstances extends ParallelInstances1 {
λ[OptionT[M, ?] ~> Nested[F, Option, ?]](optT => Nested(P.parallel(optT.value)))
}

implicit def catsStdNonEmptyParallelForZipList[A]: NonEmptyParallel[List, ZipList] =
new NonEmptyParallel[List, ZipList] {

def flatMap: FlatMap[List] = cats.instances.list.catsStdInstancesForList
def apply: Apply[ZipList] = ZipList.catsDataCommutativeApplyForZipList

def sequential: ZipList ~> List =
λ[ZipList ~> List](_.value)

def parallel: List ~> ZipList =
λ[List ~> ZipList](v => new ZipList(v))
}

implicit def catsStdNonEmptyParallelForZipVector[A]: NonEmptyParallel[Vector, ZipVector] =
new NonEmptyParallel[Vector, ZipVector] {

def flatMap: FlatMap[Vector] = cats.instances.vector.catsStdInstancesForVector
def apply: Apply[ZipVector] = ZipVector.catsDataCommutativeApplyForZipVector

def sequential: ZipVector ~> Vector =
λ[ZipVector ~> Vector](_.value)

def parallel: Vector ~> ZipVector =
λ[Vector ~> ZipVector](v => new ZipVector(v))
}

implicit def catsStdParallelForZipStream[A]: Parallel[Stream, ZipStream] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same idea as above, if we can't test it, maybe moving to alleycats?

new Parallel[Stream, ZipStream] {

def monad: Monad[Stream] = cats.instances.stream.catsStdInstancesForStream
def applicative: Applicative[ZipStream] = ZipStream.catsDataAlternativeForZipStream

def sequential: ZipStream ~> Stream =
λ[ZipStream ~> Stream](_.value)

def parallel: Stream ~> ZipStream =
λ[Stream ~> ZipStream](v => new ZipStream(v))
}


implicit def catsParallelForEitherTNestedParallelValidated[F[_], M[_], E: Semigroup]
(implicit P: Parallel[M, F]): Parallel[EitherT[M, E, ?], Nested[F, Validated[E, ?], ?]] =
Expand Down
1 change: 1 addition & 0 deletions js/src/test/scala/cats/tests/FutureTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class FutureTests extends CatsSuite {
}
}


implicit val throwableEq: Eq[Throwable] =
Eq.by[Throwable, String](_.toString)

Expand Down
1 change: 1 addition & 0 deletions jvm/src/test/scala/cats/tests/FutureSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class FutureSuite extends CatsSuite {
implicit def cogen[A: Cogen]: Cogen[Future[A]] =
Cogen[Future[A]] { (seed: Seed, t: Future[A]) => Cogen[A].perturb(seed, Await.result(t, timeout)) }


implicit val throwableEq: Eq[Throwable] =
Eq.by[Throwable, String](_.toString)

Expand Down
Loading