-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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 distributive typeclass and some instances #2046
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
a87b82b
Add distributive typeclass and some instances
coltfred 30312b1
Add syntax to functor + distributive
coltfred 5d14de2
Scalastyle
coltfred 1f3962c
add Tuple2K instance
coltfred 76915e6
Move Functor requirement off the class
coltfred 0735388
WIP laws cosequence and composition
coltfred 87db30d
Add rest of the tests
coltfred 8499505
Merge branch 'master' into addDistributive
coltfred d646d83
tuple2k test
coltfred 85d24a2
Merge branch 'master' into addDistributive
coltfred fc59e26
Add Mima exceptions
b5daed3
address code review
coltfred 7a2408a
Expand test and fix scalastyle
coltfred b686896
add more mima exceptions
kailuowang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,22 @@ | ||
package cats | ||
import simulacrum.typeclass | ||
|
||
@typeclass trait Distributive[F[_]] extends Functor[F] { self => | ||
|
||
/** | ||
* Given a function which returns a distributive `F`, apply that value across the structure G. | ||
*/ | ||
def distribute[G[_]: Functor, A, B](ga: G[A])(f: A => F[B]): F[G[B]] | ||
|
||
/** | ||
* Given a Functor G which wraps some distributive F, distribute F across the G. | ||
*/ | ||
def cosequence[G[_]: Functor, A](ga: G[F[A]]): F[G[A]] = distribute(ga)(identity) | ||
|
||
// Distributive composes | ||
def compose[G[_]](implicit G0: Distributive[G]): Distributive[λ[α => F[G[α]]]] = | ||
new ComposedDistributive[F, G] { | ||
implicit def F = self | ||
implicit def G = G0 | ||
} | ||
} |
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
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,14 @@ | ||
package cats | ||
package syntax | ||
|
||
import cats.evidence.=== | ||
|
||
trait DistributiveSyntax extends Distributive.ToDistributiveOps { | ||
implicit final def catsSyntaxDistributiveOps[F[_]: Functor, A](fa: F[A]): DistributiveOps[F, A] = new DistributiveOps[F, A](fa) | ||
} | ||
|
||
// Add syntax to functor as part of importing distributive syntax. | ||
final class DistributiveOps[F[_], A](val fa: F[A]) extends AnyVal { | ||
def distribute[G[_], B](f: A => G[B])(implicit G: Distributive[G], F: Functor[F]): G[F[B]] = G.distribute(fa)(f) | ||
def cosequence[G[_], B](implicit G: Distributive[G], F: Functor[F], ev: A === G[B]): G[F[B]] = G.cosequence(ev.substitute(fa)) | ||
} |
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,37 @@ | ||
package cats | ||
package laws | ||
|
||
import cats.Id | ||
import cats.data.Nested | ||
import cats.syntax.distributive._ | ||
|
||
trait DistributiveLaws[F[_]] extends FunctorLaws[F] { | ||
implicit override def F: Distributive[F] | ||
|
||
def cosequenceIdentity[A](fa: F[A]): IsEq[F[A]] = { | ||
F.cosequence[Id, A](fa) <-> fa | ||
} | ||
|
||
def cosequenceTwiceIsId[A, M[_]](fma: F[M[A]])(implicit M: Distributive[M]): IsEq[F[M[A]]] = { | ||
val result = F.cosequence(M.cosequence(fma)) | ||
fma <-> result | ||
} | ||
|
||
def composition[A, B, C, M[_], N[_]]( | ||
ma: M[A], | ||
f: A => F[B], | ||
g: B => N[C] | ||
)(implicit | ||
N: Distributive[N], | ||
M: Functor[M] | ||
): IsEq[Nested[F, N, M[C]]] = { | ||
val rhs = ma.distribute[Nested[F, N, ?], C](a => Nested(F.map(f(a))(g))) | ||
val lhs = Nested(F.map(ma.distribute(f))(fb => fb.distribute(g))) | ||
lhs <-> rhs | ||
} | ||
} | ||
|
||
object DistributiveLaws { | ||
def apply[F[_]](implicit ev: Distributive[F]): DistributiveLaws[F] = | ||
new DistributiveLaws[F] { def F: Distributive[F] = ev } | ||
} |
43 changes: 43 additions & 0 deletions
43
laws/src/main/scala/cats/laws/discipline/DistributiveTests.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,43 @@ | ||
package cats | ||
package laws | ||
package discipline | ||
|
||
import org.scalacheck.{Arbitrary, Cogen, Prop} | ||
import Prop._ | ||
|
||
trait DistributiveTests[F[_]] extends FunctorTests[F] { | ||
def laws: DistributiveLaws[F] | ||
|
||
def distributive[A: Arbitrary, B: Arbitrary, C: Arbitrary, X[_]: Functor, Y[_]: Distributive](implicit | ||
ArbFA: Arbitrary[F[A]], | ||
ArbFB: Arbitrary[F[B]], | ||
ArbXA: Arbitrary[X[A]], | ||
ArbYC: Arbitrary[Y[C]], | ||
ArbFYA: Arbitrary[F[Y[A]]], | ||
CogenA: Cogen[A], | ||
CogenB: Cogen[B], | ||
CogenC: Cogen[C], | ||
EqFA: Eq[F[A]], | ||
EqFC: Eq[F[C]], | ||
EqA: Eq[A], | ||
EqFYXC: Eq[F[Y[X[C]]]], | ||
EqFYA: Eq[F[Y[A]]], | ||
EqYFB: Eq[Y[F[B]]] | ||
): RuleSet = { | ||
new RuleSet { | ||
def name: String = "distributive" | ||
def bases: Seq[(String, RuleSet)] = Nil | ||
def parents: Seq[RuleSet] = Seq(functor[A, B, C]) | ||
def props: Seq[(String, Prop)] = Seq( | ||
"distributive identity" -> forAll(laws.cosequenceIdentity[A] _), | ||
"distributive composition" -> forAll(laws.composition[A, B, C, X, Y] _), | ||
"distributive double cosequence identity" -> forAll(laws.cosequenceTwiceIsId[A, Y] _) | ||
) | ||
} | ||
} | ||
} | ||
|
||
object DistributiveTests { | ||
def apply[F[_]: Distributive]: DistributiveTests[F] = | ||
new DistributiveTests[F] { def laws: DistributiveLaws[F] = DistributiveLaws[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
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should add another class for
cosequence
, we wouldn't needcats.evidence
then:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, not sure I see a reason why that's better? The evidence constraint is on just the one method and it saves the extra class for syntax. Is there a reason it should be preferred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you're right, disregard me! :D