-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
180 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package cats | ||
|
||
import cats.functor.Bifunctor | ||
|
||
/** | ||
* A type class abstracting over types that give rise to two independent [[cats.Traverse]]s. | ||
*/ | ||
trait Bitraverse[F[_, _]] extends Bifoldable[F] with Bifunctor[F] { self => | ||
/** Traverse each side of the structure with the given functions */ | ||
def bitraverse[G[_]: Applicative, A, B, C, D](fab: F[A, B])(f: A => G[C], g: B => G[D]): G[F[C, D]] | ||
|
||
/** Sequence each side of the structure with the given functions */ | ||
def bisequence[G[_]: Applicative, A, B](fab: F[G[A], G[B]]): G[F[A, B]] = | ||
bitraverse(fab)(identity, identity) | ||
|
||
/** If F and G are both [[cats.Bitraverse]] then so is their composition F[G[_, _], G[_, _]] */ | ||
def compose[G[_, _]](implicit ev: Bitraverse[G]): Bifoldable[Lambda[(A, B) => F[G[A, B], G[A, B]]]] = | ||
new CompositeBitraverse[F, G] { | ||
val F = self | ||
val G = ev | ||
} | ||
|
||
override def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] = | ||
bitraverse[Id, A, B, C, D](fab)(f, g) | ||
} | ||
|
||
object Bitraverse { | ||
def apply[F[_, _]](implicit F: Bitraverse[F]): Bitraverse[F] = F | ||
} | ||
|
||
trait CompositeBitraverse[F[_, _], G[_, _]] | ||
extends Bitraverse[Lambda[(A, B) => F[G[A, B], G[A, B]]]] | ||
with CompositeBifoldable[F, G] { | ||
def F: Bitraverse[F] | ||
def G: Bitraverse[G] | ||
|
||
def bitraverse[H[_]: Applicative, A, B, C, D]( | ||
fab: F[G[A, B], G[A, B]])( | ||
f: A => H[C], g: B => H[D] | ||
): H[F[G[C, D], G[C, D]]] = | ||
F.bitraverse(fab)( | ||
gab => G.bitraverse(gab)(f, g), | ||
gab => G.bitraverse(gab)(f, g) | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package cats | ||
package syntax | ||
|
||
trait BitraverseSyntax { | ||
implicit def bitraverseSyntax[F[_, _]: Bitraverse, A, B](fab: F[A, B]): BitraverseOps[F, A, B] = | ||
new BitraverseOps[F, A, B](fab) | ||
} | ||
|
||
final class BitraverseOps[F[_, _], A, B](fab: F[A, B])(implicit F: Bitraverse[F]) { | ||
def bitraverse[G[_]: Applicative, C, D](f: A => G[C], g: B => G[D]): G[F[C, D]] = | ||
F.bitraverse(fab)(f, g) | ||
|
||
def sequence[G[_], C, D](implicit G: Applicative[G], evLeft: A =:= G[C], evRight: B =:= G[D]): G[F[C, D]] = | ||
F.bisequence(fab.asInstanceOf[F[G[C], G[D]]]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package cats | ||
package laws | ||
|
||
trait BitraverseLaws[F[_, _]] extends BifoldableLaws[F] with BifunctorLaws[F] { | ||
implicit override def F: Bitraverse[F] | ||
|
||
def bitraverseIdentity[A, B](fab: F[A, B]): IsEq[F[A, B]] = | ||
fab <-> F.bitraverse[Id, A, B, A, B](fab)(identity, identity) | ||
|
||
def bitraverseCompose[G[_], A, B, C, D, E, H]( | ||
fab: F[A, B], | ||
f: A => G[C], | ||
g: B => G[D], | ||
h: C => G[E], | ||
i: D => G[H] | ||
)(implicit | ||
G: Applicative[G] | ||
): IsEq[G[G[F[E, H]]]] = { | ||
val fg = F.bitraverse(fab)(f, g) | ||
val hi = G.map(fg)(f => F.bitraverse(f)(h, i)) | ||
|
||
type GCompose[X] = G[G[X]] | ||
val GCompose = G.compose[G] | ||
|
||
val c = | ||
F.bitraverse[GCompose, A, B, E, H](fab)( | ||
a => G.map(f(a))(h), | ||
b => G.map(g(b))(i) | ||
)(GCompose) | ||
|
||
hi <-> c | ||
} | ||
} | ||
|
||
object BitraverseLaws { | ||
def apply[F[_, _]](implicit ev: Bitraverse[F]): BitraverseLaws[F] = | ||
new BitraverseLaws[F] { def F: Bitraverse[F] = ev } | ||
} |
47 changes: 47 additions & 0 deletions
47
laws/src/main/scala/cats/laws/discipline/BitraverseTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package cats | ||
package laws | ||
package discipline | ||
|
||
import org.scalacheck.Arbitrary | ||
import org.scalacheck.Prop.forAll | ||
|
||
trait BitraverseTests[F[_, _]] extends BifoldableTests[F] with BifunctorTests[F] { | ||
def laws: BitraverseLaws[F] | ||
|
||
def bitraverse[G[_], A, B, C, D, E, H](implicit | ||
G: Applicative[G], | ||
C: Monoid[C], | ||
ArbFAB: Arbitrary[F[A, B]], | ||
ArbFAD: Arbitrary[F[A, D]], | ||
ArbGC: Arbitrary[G[C]], | ||
ArbGD: Arbitrary[G[D]], | ||
ArbGE: Arbitrary[G[E]], | ||
ArbGH: Arbitrary[G[H]], | ||
ArbA: Arbitrary[A], | ||
ArbB: Arbitrary[B], | ||
ArbC: Arbitrary[C], | ||
ArbE: Arbitrary[E], | ||
ArbH: Arbitrary[H], | ||
EqFAB: Eq[F[A, B]], | ||
EqFAD: Eq[F[A, D]], | ||
EqFAH: Eq[F[A, H]], | ||
EqFCD: Eq[F[C, D]], | ||
EqFCH: Eq[F[C, H]], | ||
EqGGFEH: Eq[G[G[F[E, H]]]], | ||
EqC: Eq[C] | ||
): RuleSet = | ||
new RuleSet { | ||
val name = "bitraverse" | ||
val parents = Seq(bifoldable[A, B, C], bifunctor[A, B, C, D, E, H]) | ||
val bases = Seq.empty | ||
val props = Seq( | ||
"bitraverse identity" -> forAll(laws.bitraverseIdentity[A, B] _), | ||
"bitraverse composition" -> forAll(laws.bitraverseCompose[G, A, B, C, D, E, H] _) | ||
) | ||
} | ||
} | ||
|
||
object BitraverseTests { | ||
def apply[F[_, _]: Bitraverse]: BitraverseTests[F] = | ||
new BitraverseTests[F] { def laws: BitraverseLaws[F] = BitraverseLaws[F] } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
package cats | ||
package tests | ||
|
||
import cats.laws.discipline.{BifoldableTests, SerializableTests} | ||
import cats.laws.discipline.{BitraverseTests, SerializableTests} | ||
import cats.laws.discipline.eq.tuple2Eq | ||
|
||
class TupleTests extends CatsSuite { | ||
checkAll("Tuple2", BifoldableTests[Tuple2].bifoldable[Int, Int, Int]) | ||
checkAll("Bifoldable[Tuple2]", SerializableTests.serializable(Bifoldable[Tuple2])) | ||
checkAll("Tuple2", BitraverseTests[Tuple2].bitraverse[Option, Int, Int, Int, String, String, String]) | ||
checkAll("Bitraverse[Tuple2]", SerializableTests.serializable(Bitraverse[Tuple2])) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters