Skip to content
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

More instances for prod #1402

Merged
merged 11 commits into from
Oct 25, 2016
Merged

More instances for prod #1402

merged 11 commits into from
Oct 25, 2016

Conversation

pepegar
Copy link
Contributor

@pepegar pepegar commented Oct 7, 2016

Creating more instances for Prod:

  • Monad
  • Foldable
  • Traverse
  • Order
  • MonadCombine
  • Show

fixes #1375

@codecov-io
Copy link

codecov-io commented Oct 7, 2016

Current coverage is 91.68% (diff: 100%)

Merging #1402 into master will decrease coverage by <.01%

@@             master      #1402   diff @@
==========================================
  Files           240        240          
  Lines          3610       3632    +22   
  Methods        3546       3568    +22   
  Messages          0          0          
  Branches         63         63          
==========================================
+ Hits           3310       3330    +20   
- Misses          300        302     +2   
  Partials          0          0          

Powered by Codecov. Last update a392654...867b2a2

@pepegar
Copy link
Contributor Author

pepegar commented Oct 13, 2016

Hi @adelbertc is there something else I can do here?

checkAll("MonadCombine[Prod[ListWrapper, ListWrapper, ?]]", SerializableTests.serializable(MonadCombine[Prod[ListWrapper, ListWrapper, ?]]))
}

test("order") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

def F: Order[F[A]] = FF
def G: Order[G[A]] = GF
}
implicit def catsDataShowForProd[F[_], G[_], A](implicit FF: Show[F[A]], GF: Show[G[A]]): Show[Prod[F, G, A]] = new ProdShow[F, G, A] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one can probably be moved up to ProdInstances right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

}

private[data] sealed abstract class ProdInstances9 {
implicit def catsDataOrderForProd[F[_], G[_], A](implicit FF: Order[F[A]], GF: Order[G[A]]): Order[Prod[F, G, A]] = new ProdOrder[F, G, A] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can probably be moved up to one sub class down from the Eq instance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

}

private[data] sealed abstract class ProdInstances0 extends ProdInstances1 {
implicit def catsDataMonoidKForProd[F[_], G[_]](implicit FF: MonoidK[F], GG: MonoidK[G]): MonoidK[λ[α => Prod[F, G, α]]] = new ProdMonoidK[F, G] {
def F: MonoidK[F] = FF
def G: MonoidK[G] = GG
}

implicit def catsDataOrderForProd[F[_], G[_], A](implicit FF: Order[F[A]], GF: Order[G[A]]): Order[Prod[F, G, A]] = new ProdOrder[F, G, A] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @adelbertc pointed out, Order instance should have higher priority than Eq since it's more specific. I think we should move this instance to ProdInstances and the Eq instance down here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sure! I misunderstood @adelbertc in the previous comment. Now it's done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much!

@travisbrown travisbrown mentioned this pull request Oct 18, 2016
13 tasks
def G: MonadCombine[G] = GF
}
}

Copy link
Contributor

@kailuowang kailuowang Oct 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular case, to ensure the more specific instance having the highest priority, we basically want to ensure that instances of typeclasses who are lower in the inheritance tree are also lower in the instance trait inheritance tree. For example, Monad inherits Functor and thus is more "specific" than Functor, so it should be in an instance trait with higher priority (0 - 3) than where Functor is (4).
So, we need to rearrange the instances to that order.
MonadCombine <: Altenative
MonadCombine <: Monad <: Applicative <: Apply <: Functor
Traverse <: Foldable
Traverse <: Functor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out, I didn't think on that!

I've done the changes in 000a583

def F: MonadCombine[F] = FF
def G: MonadCombine[G] = GF
private[data] sealed abstract class ProdInstances7 {
implicit def catsDataAlternativeForProd[F[_], G[_]](implicit FF: Alternative[F], GG: Alternative[G]): Alternative[λ[α => Prod[F, G, α]]] = new ProdAlternative[F, G] {
Copy link
Contributor

@kailuowang kailuowang Oct 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! We are getting close.
how about we do
ProdInstances: MonadCombine, Order, Show ,Traverse, Contravariant
ProdInstances0: Alternative, Monad, Eq, Foldable
ProdInstances1: MonoidK, Applicative
ProdInstances2: SemigroupK, Apply
ProdInstances3: Functor

I might make some mistakes here too.
You may find this diagram helpful
https://camo.githubusercontent.com/28086d65ea5688b722ef4c19ee70e1974c5f4cb0/687474703a2f2f766972656f2e6f72672f746d702f74797065636c61737365732e737667

Copy link
Contributor

@kailuowang kailuowang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! We are getting close.
how about we do
ProdInstances: MonadCombine, Order, Show ,Traverse, Contravariant
ProdInstances0: Alternative, Monad, Eq, Foldable
ProdInstances1: MonoidK, Applicative
ProdInstances2: SemigroupK, Apply
ProdInstances3: Functor

I might make some mistakes here too.
You may find this diagram helpful https://camo.githubusercontent.com/28086d65ea5688b722ef4c19ee70e1974c5f4cb0/687474703a2f2f766972656f2e6f72672f746d702f74797065636c61737365732e737667

@pepegar
Copy link
Contributor Author

pepegar commented Oct 20, 2016

Yep, I absolutely find that diagram helpful! Now that I can see at a glance what's the hierarchy between all typeclasses, your last structure seems correct!

BTW, is this diagram accesible somewhere in the docs?

@@ -46,20 +57,45 @@ private[data] sealed abstract class ProdInstances2 extends ProdInstances3 {
}

private[data] sealed abstract class ProdInstances3 extends ProdInstances4 {
implicit def catsDataMonadForProd[F[_], G[_]](implicit FM: Monad[F], GM: Monad[G]): Monad[λ[α => Prod[F, G, α]]] = new ProdMonad[F, G] {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can replace these λ[α => Prod[F, G, α]] by just Prod[F, G, ?].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sure!

But, what's the difference between the generated code of one and the other?

@kailuowang
Copy link
Contributor

@pepegar I just resurrected a PR to add the hierarchy diagram to the site. #1416


test("show") {
forAll { (l1: Option[Int], l2: Option[Int]) =>
val showOptionInt = implicitly[Show[Option[Int]]]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, but this can just be val showOptionInt = Show[Option[Int]], right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, you're right :)

@pepegar
Copy link
Contributor Author

pepegar commented Oct 24, 2016

@kailuowang If I structure the code as you suggested:

ProdInstances: MonadCombine, Order, Show ,Traverse, Contravariant
ProdInstances0: Alternative, Monad, Eq, Foldable
ProdInstances1: MonoidK, Applicative
ProdInstances2: SemigroupK, Apply
ProdInstances3: Functor

I find ambiguous implicit values for MonadCombine and Traverse:

[info] Set current project to cats (in build file:/Users/pepe/projects/scala/cats/)
[success] Total time: 2 s, completed Oct 24, 2016 4:19:14 PM
[info] Compiling 3 Scala sources to /Users/pepe/projects/scala/cats/tests/.jvm/target/scala-2.11/test-classes...
[error] /Users/pepe/projects/scala/cats/tests/src/test/scala/cats/tests/ProdTests.scala:12: ambiguous implicit values:
[error]  both method catsDataMonadCombineForProd in class ProdInstances of type [F[_], G[_]](implicit FF: cats.MonadCombine[F], implicit GF: cats.MonadCombine[G])cats.MonadCombine[[α]cats.data.Prod[F,G,α]]
[error]  and method catsDataTraverseForProd in class ProdInstances of type [F[_], G[_]](implicit FF: cats.Traverse[F], implicit GF: cats.Traverse[G])cats.Traverse[[α]cats.data.Prod[F,G,α]]
[error]  match expected type cats.functor.Invariant[[γ$0$]cats.data.Prod[Option,[+A]List[A],γ$0$]]
[error]   implicit val iso = CartesianTests.Isomorphisms.invariant[Prod[Option, List, ?]]
[error]                                                           ^
[error] /Users/pepe/projects/scala/cats/tests/src/test/scala/cats/tests/ProdTests.scala:13: could not find implicit value for parameter ev: cats.laws.discipline.CartesianTests.Isomorphisms[[α]cats.data.Prod[Option,[+A]List[A],α]]
[error]   checkAll("Prod[Option, List, Int]", CartesianTests[λ[α => Prod[Option, List, α]]].cartesian[Int, Int, Int])
[error]                                                     ^
[error] /Users/pepe/projects/scala/cats/tests/src/test/scala/cats/tests/ProdTests.scala:16: could not find implicit value for parameter iso: cats.laws.discipline.CartesianTests.Isomorphisms[[α]cats.data.Prod[Option,[+A]List[A],α]]
[error]   checkAll("Prod[Option, List, Int]", AlternativeTests[λ[α => Prod[Option, List, α]]].alternative[Int, Int, Int])
[error]                                                                                                  ^
[error] three errors found
[error] (testsJVM/test:compileIncremental) Compilation failed

What do you think on the following structure?

ProdInstances: MonadCombine, Order, Show, Contravariant
ProdInstances0: Alternative, Monad, Eq, Traverse
ProdInstances1: MonoidK, Applicative, Foldable
ProdInstances2: SemigroupK, Apply
ProdInstances3: Functor

The latter seems to work fine for me.

@kailuowang
Copy link
Contributor

@pepegar My bad, your suggestion looks fine to me.

@kailuowang
Copy link
Contributor

👍 on travis green

@non
Copy link
Contributor

non commented Oct 25, 2016

LGTM 👍

@non non merged commit 5c00fdf into typelevel:master Oct 25, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More cats.data.Prod instances
6 participants