-
-
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 Arrow Choice #2096
Add Arrow Choice #2096
Changes from all commits
a8de85b
f315767
7369b6f
791d9d1
93574b3
191c68c
48d9458
8b5d497
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package cats | ||
package arrow | ||
|
||
import simulacrum.typeclass | ||
|
||
/** | ||
* Must obey the laws defined in cats.laws.ArrowChoiceLaws. | ||
*/ | ||
@typeclass trait ArrowChoice[F[_, _]] extends Arrow[F] with Choice[F] { self => | ||
|
||
/** | ||
* ArrowChoice yields Arrows with choice, allowing distribution | ||
* over coproducts. | ||
* | ||
* Given two `F`s (`f` and `g`), create a new `F` with | ||
* domain the coproduct of the domains of `f` and `g`, | ||
* and codomain the coproduct of the codomains of `f` and `g`. | ||
* This is the sum notion to `split`'s product. | ||
* | ||
* Example: | ||
* {{{ | ||
* scala> import cats.implicits._ | ||
* scala> val toLong: Int => Long = _.toLong | ||
* scala> val toDouble: Float => Double = _.toDouble | ||
* scala> val f: Either[Int, Float] => Either[Long, Double] = toLong +++ toDouble | ||
* scala> f(Left(3)) | ||
* res0: Either[Long,Double] = Left(3) | ||
* scala> f(Right(3)) | ||
* res1: Either[Long,Double] = Right(3.0) | ||
* }}} | ||
*/ | ||
@simulacrum.op("+++", alias = true) | ||
def choose[A, B, C, D](f: F[A, C])(g: F[B, D]): F[Either[A, B], Either[C, D]] | ||
|
||
def left[A, B, C](fab: F[A, B]): F[Either[A, C], Either[B, C]] = | ||
choose(fab)(lift(identity[C])) | ||
|
||
def right[A, B, C](fab: F[A, B]): F[Either[C, A], Either[C, B]] = | ||
choose(lift(identity[C]))(fab) | ||
|
||
override def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Either[A, B], C] = | ||
rmap(choose(f)(g))(_.fold(identity, identity)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call, I can add. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package cats | ||
package syntax | ||
|
||
import cats.arrow.ArrowChoice | ||
|
||
trait ArrowChoiceSyntax extends ArrowChoice.ToArrowChoiceOps |
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.
This is never tested by law as I noticed from the law set defined in Haskell. Thus it doesn't have any test coverage.
Shall we add a law for this something like
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.
I actually added symmetric versions for all the laws last night for that reason, but it takes the method well over 50 lines. Something like that sounds like a more reasonable way to get similar effect. I'll try it out today, it certainly should work.