-
Notifications
You must be signed in to change notification settings - Fork 451
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
Contravariant & Invariant #975
Conversation
|
||
init { | ||
testLaws( | ||
InvariantLaws.laws(Monoid.invariant<Int>(), { Int.monoid() }, EQ) |
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.
@pakoito It seems like our experiment success at compiling but tests are failing 🤔
fun G(): Invariant<G> | ||
|
||
override fun <A, B> Kind<Nested<F, G>, A>.imap(f: (A) -> B, g: (B) -> A): Kind<Nested<F, G>, B> = | ||
F().run { unnest().imap({ ga -> G().run { ga.imap(f, g) } }, { gb -> G().run { gb.imap(g, f) } }) }.nest() |
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.
There's a chance this doesn't work on Android on the D8 compiler due to a problem with scopes and run
. Can you please move each of the lambdas in imap to a separate line?
F().run { | ||
val fl: (Kind<G, A>) -> Kind<G, B> = { ga -> G().run { ga.contramap(g) } } | ||
val fr: (Kind<G, B>) -> Kind<G, A> = { gb -> G().run { gb.contramap(f) } } | ||
unnest().imap(fl, fr) |
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.
Sorry, my bad. Take these out of the F()
run block I mean.
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.
👌
3d5b50e
to
e467b97
Compare
I've run all the tests locally and it seems like Monoid is passing Invariant Laws now! So now I'm going to add an Invariant instance for Semigroup and that should be it for Invariant. EDIT: When I add the Can we fix this? Or should we just offer one instance of Invariant for Monoid or Semigroup? |
@@ -11,7 +11,7 @@ import org.junit.runner.RunWith | |||
class MonoidTest : UnitSpec() { | |||
|
|||
val EQ: Eq<MonoidOf<Int>> = Eq.invoke { a, b -> | |||
a.fix() == b.fix() | |||
a.fix().run { 3.combine(1) } == b.fix().run { 3.combine(1) } |
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.
You figured out why it didn't work :D Well done!
Codecov Report
@@ Coverage Diff @@
## master #975 +/- ##
============================================
+ Coverage 47.8% 47.96% +0.15%
- Complexity 695 702 +7
============================================
Files 320 325 +5
Lines 8099 8200 +101
Branches 753 753
============================================
+ Hits 3872 3933 +61
- Misses 3943 3984 +41
+ Partials 284 283 -1
Continue to review full report at Codecov.
|
Try making ForMonoid inherit ForSemigroup, as the F in Kind is covariant. Subtyping sucks :) Test thoroughly. |
I'm also having some troubles to create a class Function1<I, out O>(val f: (I) -> O) {
fun <B> contramap(f: (B) -> I): Function1<B, O> = (this.f compose f).k()
} But now I can't use it when I am defining the interface Function1ContravariantInstance<I> : Contravariant<Function1PartialOf<I>> {
override fun <A, B> Kind<Function1PartialOf<I>, A>.contramap(f: (B) -> A): Function1<I, B> =
fix().contramap(f)
} The editor tells me that override fun <A, B> Kind<Function1PartialOf<I>, A>.contramap(f: (B) -> I): Function1<B, A> |
@Cotel Push it and I'll take a look |
96612ab
to
5c422d8
Compare
@Cotel can't be done, same problem as the left functor from the other day |
|
||
testLaws( | ||
InvariantLaws.laws(ComposedInvariant(Option.functor(), NonEmptyList.functor()), cf, EQ_OPTION_NEL), | ||
InvariantLaws.laws(ComposedInvariantCovariant(Option.functor(), NonEmptyList.functor()), cf, EQ_OPTION_NEL), | ||
InvariantLaws.laws(ComposedInvariantContravariant(Option.functor(), Function1.contravariant<Int>()), cf2, EQ_OPTION_FN1), |
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.
TestLaws deduplicates tests based on name. That means only one of these will be run. Split 2 of them into a new call to testLaws.
I've been looking for The only thing that remains is to test the laws for |
I would like to finish this asap and start something related with comonadic UIs but I was stuck and I'm quite busy right now. I feel bad for keeping this PR open for so long with no activity 😅 |
I'm traveling, let's talk in September :D |
941c721
to
3fa098c
Compare
Hey! I might have some spare time tomorrow and I would like to close this and start working on another issue or something 😁 |
I'm sorry but I really don't know what is failing here. I suppose that the laws which are failing are val cf2: (Int) -> Kind<Nested<ForOption, Conested<ForFunction1, Int>>, Int> = { x: Int ->
Some({ y: Int -> x + y }.k().conest()).nest()
} val EQ_OPTION_FN1: Eq<NestedType<ForOption, Conested<ForFunction1, Int>, Int>> = Eq { a, b ->
a.unnest().fix() == b.unnest().fix()
} Any ideas? 😅 |
I may take a look directly in the afternoon. Meanwhile, use the extfun |
God bless that |
@Cotel It's saved my ass more times that I'm willing to admit hahaha Gotta give a last check and we'll go green ;) |
@@ -36,7 +36,15 @@ class ComposedInstancesTest : UnitSpec() { | |||
} | |||
|
|||
val EQ_OPTION_FN1: Eq<NestedType<ForOption, Conested<ForFunction1, Int>, Int>> = Eq { a, b -> | |||
a.unnest().fix() == b.unnest().fix() | |||
a.unnest().fix().fold( |
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.
Cheezus fucking chrixt
@@ -16,6 +13,7 @@ class ConstTest : UnitSpec() { | |||
init { | |||
ForConst(Int.monoid()) extensions { | |||
testLaws( | |||
InvariantLaws.laws(this, { Const(it) }, Eq.any()), |
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.
InvariantLaws should be part of FunctorLaws, so it's tested by ApplicativeLaws!
|
||
testLaws( | ||
InvariantLaws.laws(ComposedInvariant(Option.functor(), NonEmptyList.functor()), cf, EQ_OPTION_NEL), |
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.
Same as above, InvariantLaws should be part of FunctorLaws.
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.
FuntorLaws are being used at line 74. Should I remove that line too?
object ContravariantLaws { | ||
|
||
inline fun <F> laws(CF: Contravariant<F>, noinline cf: (Int) -> Kind<F, Int>, EQ: Eq<Kind<F, Int>>): List<Law> = | ||
listOf( |
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.
In here ContravariantLaws imply InvariantLaws also pass, so replace this line with:
InvariantLaws.laws(...) + listOf(
You'll need to do the same in FunctorLaws.
@@ -211,20 +348,20 @@ interface ComposedBifoldable<F, G> : Bifoldable<Nested<F, G>> { | |||
|
|||
fun G(): Bifoldable<G> | |||
|
|||
override fun <A, B, C> BiunnestedType<F, G, A, B>.bifoldLeft(c: C, f: (C, A) -> C, g: (C, B) -> C): C = F().run { | |||
override fun <A, B, C> BinestedType<F, G, A, B>.bifoldLeft(c: C, f: (C, A) -> C, g: (C, B) -> C): C = F().run { |
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.
Are we sure of this change, or was it part of the merge?
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've checked the history and this is part from our changes, related to fa50cf1
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.
Right, right, they're correct, there's a couple of fixes to other that were wrong.
Cool, only the test left 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.
One last fix: the FunctorLaws and ContravariantLaws require also passing the InvariantLaws. With that change we're ready to go!!
🎉 |
Adding Contravariant & Invariant typeclasses and instances.