-
-
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.
Also: - Add MonadCombine separate - Add serializability check for Bifunctor[Xor]
- Loading branch information
Showing
13 changed files
with
166 additions
and
4 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,23 @@ | ||
package cats | ||
|
||
/** | ||
* A type class abstracting over types that give rise to two independent [[cats.Foldable]]s. | ||
*/ | ||
trait Bifoldable[F[_, _]] extends Serializable { | ||
/** Collapse the structure with a left-associative function */ | ||
def bifoldLeft[A, B, C](fab: F[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C | ||
|
||
/** Collapse the structure with a right-associative function */ | ||
def bifoldRight[A, B, C](fab: F[A, B], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] | ||
|
||
/** Collapse the structure by mapping each element to an element of a type that has a [[cats.Monoid]] */ | ||
def bifoldMap[A, B, C](fab: F[A, B])(f: A => C)(g: B => C)(implicit C: Monoid[C]): C = | ||
bifoldLeft(fab, C.empty)( | ||
(c: C, a: A) => C.combine(c, f(a)), | ||
(c: C, b: B) => C.combine(c, g(b)) | ||
) | ||
} | ||
|
||
object Bifoldable { | ||
def apply[F[_, _]](implicit F: Bifoldable[F]): Bifoldable[F] = 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
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 |
---|---|---|
|
@@ -15,3 +15,4 @@ trait AllInstances | |
with BigIntInstances | ||
with BigDecimalInstances | ||
with FutureInstances | ||
with TupleInstances |
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 std | ||
|
||
trait TupleInstances extends Tuple2Instances | ||
|
||
sealed trait Tuple2Instances { | ||
implicit val tuple2Bifoldable: Bifoldable[Tuple2] = | ||
new Bifoldable[Tuple2] { | ||
def bifoldLeft[A, B, C](fab: (A, B), c: C)(f: (C, A) => C, g: (C, B) => C): C = | ||
g(f(c, fab._1), fab._2) | ||
|
||
def bifoldRight[A, B, C](fab: (A, B), c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = | ||
g(fab._2, f(fab._1, c)) | ||
} | ||
} |
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,29 @@ | ||
package cats | ||
package laws | ||
|
||
trait BifoldableLaws[F[_, _]] { | ||
implicit def F: Bifoldable[F] | ||
|
||
def bifoldLeftConsistentWithBifoldMap[A, B, C](fab: F[A, B], f: A => C, g: B => C)(implicit C: Monoid[C]): IsEq[C] = { | ||
val expected = F.bifoldLeft(fab, C.empty)( | ||
(c: C, a: A) => C.combine(c, f(a)), | ||
(c: C, b: B) => C.combine(c, g(b)) | ||
) | ||
expected <-> F.bifoldMap(fab)(f)(g) | ||
} | ||
|
||
def bifoldRightConsistentWithBifoldMap[A, B, C](fab: F[A, B], f: A => C, g: B => C)(implicit C: Monoid[C]): IsEq[C] = { | ||
val expected = F.bifoldRight(fab, Later(C.empty))( | ||
(a: A, ec: Eval[C]) => ec.map(c => C.combine(f(a), c)), | ||
(b: B, ec: Eval[C]) => ec.map(c => C.combine(g(b), c)) | ||
) | ||
expected.value <-> F.bifoldMap(fab)(f)(g) | ||
} | ||
} | ||
|
||
object BifoldableLaws { | ||
def apply[F[_, _]](implicit ev: Bifoldable[F]): BifoldableLaws[F] = | ||
new BifoldableLaws[F] { | ||
def F: Bifoldable[F] = ev | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
laws/src/main/scala/cats/laws/discipline/BifoldableTests.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,26 @@ | ||
package cats | ||
package laws | ||
package discipline | ||
|
||
import org.scalacheck.Arbitrary | ||
import org.scalacheck.Prop._ | ||
import org.typelevel.discipline.Laws | ||
|
||
trait BifoldableTests[F[_, _]] extends Laws { | ||
def laws: BifoldableLaws[F] | ||
|
||
def bifoldable[A: Arbitrary, B: Arbitrary, C: Arbitrary: Monoid: Eq](implicit | ||
ArbFAB: Arbitrary[F[A, B]] | ||
): RuleSet = | ||
new DefaultRuleSet( | ||
name = "bifoldable", | ||
parent = None, | ||
"bifoldLeft consistent with bifoldMap" -> forAll(laws.bifoldLeftConsistentWithBifoldMap[A, B, C] _), | ||
"bifoldRight consistent with bifoldMap" -> forAll(laws.bifoldRightConsistentWithBifoldMap[A, B, C] _) | ||
) | ||
} | ||
|
||
object BifoldableTests { | ||
def apply[F[_, _]: Bifoldable]: BifoldableTests[F] = | ||
new BifoldableTests[F] { def laws: BifoldableLaws[F] = BifoldableLaws[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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package cats | ||
package tests | ||
|
||
import cats.data.Xor | ||
import cats.laws.discipline.arbitrary.xorArbitrary | ||
import cats.laws.discipline.eq.tuple2Eq | ||
|
||
class MonadCombineTest extends CatsSuite { | ||
test("separate") { | ||
forAll { (list: List[Xor[Int, String]]) => | ||
val ints = list.collect { case Xor.Left(i) => i } | ||
val strings = list.collect { case Xor.Right(s) => s } | ||
val expected = (ints, strings) | ||
|
||
MonadCombine[List].separate(list) should === (expected) | ||
} | ||
} | ||
} |
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,9 @@ | ||
package cats | ||
package tests | ||
|
||
import cats.laws.discipline.{BifoldableTests, SerializableTests} | ||
|
||
class TupleTests extends CatsSuite { | ||
checkAll("Tuple2", BifoldableTests[Tuple2].bifoldable[Int, Int, Int]) | ||
checkAll("Bifoldable[Tuple2]", SerializableTests.serializable(Bifoldable[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