-
-
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
Invariant super class of Alternative and Decidable #2620
Comments
/cc @stephen-lazaro |
Yeah, +1. After I (finally) finish the Decideable PR, I can take a shot at this. Though do we get a genuine MonoidK in the Decideable case? I thought that symmetry didn't quite land. |
I think this will have to wait until 2.0, so no need to hurry, we've got tons of time :) |
I fixed the hierarchy, not sure what I was thinking there 😄 |
That diagram has some actually delightful symmetry, sort of reminds me of the Zassenhaus Butterfly Lemma |
To keep breakage as small as possible it might be good to either
|
@LukaJCB There's no place for Invariant add monoidal should have @typeclass
trait InvariantAddSemigroupal[F[_]] {
def invariant: Invariant[F]
def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]]
// associativity law: sum(sum(fa, fb), fc) ≃ sum(fa, sum(fb, fc))
}
@typeclass
trait InvariantAddMonoidal[F[_]] extends InvariantAddSemigroupal[F] {
def nothing: F[Nothing]
// identity law: sum(fa, nothing) ≃ sum(nothing, fa) ≃ fa
} Then, for the covariant monoidals we can derive the following (preserving arrow direction): def pure[A](a: A): F[A] = functor.map(unit)(_ => a)
// (() -> a) -> (f () -> f a)
def empty[A]: F[A] = functor.map(nothing)(absurd[A])
// (Void -> a) -> (f Void -> f a) For the contravariant monoidals we can derive (inverting arrows): def trivial[A]: F[A] = contravariant.contramap(unit)(_ => ()) // or conquer[A]: F[A]
// (a -> ()) -> (f () -> f a)
def lose[A](f: A => Nothing): F[A] = contravariant.contramap[Nothing, A](nothing)(f)
// (a -> Void) -> (f Void -> f a) So I also think we probably need to adopt naming for |
That's a good call @catostrophe. Good catch. Is it really worth switching to EDIT: Note we're quickly becoming committed to having |
@LukaJCB I incline towards option (2) but I imagine we could get by with either. (2) has the advantage of allowing us to make changes upon 2.0 if things shake out weird. |
No, I'm not too picky about names. Although we already have quite many discrepancies between cats/scalaz/haskell and it makes user experience harder. |
@catostrophe Fair point. Worth thinking about how much divergence is acceptable before it's a problem... |
@catostrophe Everything you're saying makes absolute sense to me, thanks a ton! Though I think we should discuss the issue of renaming existing type classes in a different issue, otherwise this could get out of hand quickly :) |
Of course with I wonder if we can avoid |
Maybe |
Or |
I added a WIP for the missing type classes (sans |
I just realized we have |
Should be removed in 2.0 |
I also have some arguments against the It might be misleading as in the wrong analogy we've discussed recently with @LukaJCB in gitter. For
|
@catostrophe do you mean |
Yes, I mean What does |
It means the same as |
I might've missed something but is this not BC breaking on scala 2.12? |
I honestly don't know if it is or not, it might be, but I'm not sure. It definitely breaks for 2.11 though. |
@LukaJCB Do you still want to try to get this into 2.1? |
@travisbrown let me figure out if this is binary compatible (I highly doubt it is) |
Turns out, this might be binary compatible after all! |
I may have a use case both for this and a free construction of it! (
stringLiteral("HTTP/"),
digit.imap(_ - '0')(i => (i + '0').toChar),
charLiteral('.'),
digit.imap(_ - '0')(i => (i + '0').toChar),
).imapN((_, major, _, minor) => new HttpVersion(major, minor))(httpVersion =>
((), httpVersion.major, (), httpVersion.minor)
) The free construction can be foldMapped to ... but there are also sum types, so I'm about to hit a wall. I've been studying Haskell's Free Alternative and Free Decidable. I think what I need is a Free Invariant Semiringal?! |
This ties into #1935, but also #2400 and #1932.
I think we could do a lot better with the
Alternative
hierarchy and theDecidable
PR shows, it might need some binary breaking changes.Ideally we could replicate the
*Monoidal
hierarchy, but using sum types instead. Then at the end we'd haveInvariantSemiringal
and haveAlternative
andDecidable
extend from that.Some code I came up with (names are not final by any means):
I've also written about this quite a bit in this blog post: https://typelevel.org/blog/2018/11/02/semirings.html
I made a funky looking diagram real quick:
As to why this is useful, I think this offers a really great API for codec combinators when working with e.g. circe, scodec or recently skunk.
The text was updated successfully, but these errors were encountered: