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

admit weaker typeclass instances for OptionT when the wrapped Functor… #569

Merged
merged 6 commits into from
Oct 27, 2015

Conversation

stew
Copy link
Contributor

@stew stew commented Oct 15, 2015

… is weaker

@xuwei-k
Copy link
Contributor

xuwei-k commented Oct 15, 2015

👎

scalaz/scalaz#581

@codecov-io
Copy link

Current coverage is 75.92%

Merging #569 into master will increase coverage by +0.21% as of 2b0a2b8

@@            master    #569   diff @@
======================================
  Files          157     159     +2
  Stmts         2158    2185    +27
  Branches        68      68       
  Methods          0       0       
======================================
+ Hit           1634    1659    +25
  Partial          0       0       
- Missed         524     526     +2

Review entire Coverage Diff as of 2b0a2b8

Powered by Codecov. Updated on successful CI builds.

@non
Copy link
Contributor

non commented Oct 15, 2015

Lets try to add a law here that tests consistency between ap and flatMap-- I think that is the issue @xuwei-k is bringing up.

@xuwei-k
Copy link
Contributor

xuwei-k commented Oct 15, 2015

@non
Copy link
Contributor

non commented Oct 15, 2015

Ah, I see. In order to get the tests to fail on this change we'd have to create a situation where Applicative was not a Monad.

@xuwei-k
Copy link
Contributor

xuwei-k commented Oct 15, 2015

[info] - OptionT[List, Int].monad.flatMap consistent apply *** FAILED *** (20 milliseconds)
[info]   GeneratorDrivenPropertyCheckFailedException was thrown during property evaluation.
[info]    (Discipline.scala:14)
[info]     Falsified after 20 successful property evaluations.
[info]     Location: (Discipline.scala:14)
[info]     Occurred when passed generated values (
[info]       arg0 = OptionT(List(Some(1676234460), Some(934633364), Some(2029976710), Some(830245382), Some(579257234), Some(1239180264), Some(28665143))),
[info]       arg1 = OptionT(List(None))
[info]     )
[info]     Label of failing property:
[info]       (OptionT(List(None, None, None, None, None, None, None)) ?== OptionT(List(None))) failed
[info]   org.scalatest.exceptions.GeneratorDrivenPropertyCheckFailedException:
[info]   at org.scalatest.prop.Checkers$.doCheck(Checkers.scala:403)

@non
Copy link
Contributor

non commented Oct 15, 2015

Thanks @xuwei-k.

@stew
Copy link
Contributor Author

stew commented Oct 15, 2015

yes, thanks @xuwei-k !

@ceedubs
Copy link
Contributor

ceedubs commented Oct 15, 2015

@stew should the MonadCombine instance override ap to help catch this sort of issue in the future?

@stew
Copy link
Contributor Author

stew commented Oct 16, 2015

@ceedubs I believe as it currently stands, the MonadCombine instance gets its ap definition from FlatMap:

https://github.com/non/cats/blob/master/core/src/main/scala/cats/FlatMap.scala#L29-L30

@ceedubs
Copy link
Contributor

ceedubs commented Oct 16, 2015

@stew right. I guess what I'm saying is that right now there is no test coverage on OptionT.ap. The laws will help ensure that MonadCombine[OptionT[F, ?]] has an ap that is consistent with its flatMap, but OptionT.ap has a separate implementation. Adding in an override seemed like an easy way to ensure the two were consistent. An alternative would be to add a test to ensure that they are consistent (though at that point it seems sort of silly to not just make the code guarantee that they are consistent). Does that make sense?

@stew
Copy link
Contributor Author

stew commented Oct 16, 2015

I guess. I can tell you with near certainty that the ap method there, which I implemented with flatmap, will be consistent with flatmap.

Another option is to remove ap from OptionT. I'm not sure the circumstance when someone uses ap that isn't doing so from an applicative instance.

@ceedubs
Copy link
Contributor

ceedubs commented Oct 16, 2015

@stew Removing ap from OptionT is fine with me. I just think that if it's there then we should be testing it.

@ceedubs
Copy link
Contributor

ceedubs commented Oct 16, 2015

👍

checkAll("OptionT[List, Int]", MonadTests[OptionT[List, ?]].monad[Int, Int, Int])
checkAll("OptionT[List, Int]", MonadCombineTests[OptionT[List, ?]].monad[Int, Int, Int])
checkAll("OptionT[Validated, Int]", ApplicativeTests[Validated[String,?]].applicative[Int, Int, Int])
checkAll("Functor[Map[String,Int]]", FunctorTests[Map[String,?]].functor[Int, Int, Int])
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this test here? (does not use OptionT)

stew and others added 3 commits October 18, 2015 10:07
oops, get rid of tests I didn't intend to add
@adelbertc
Copy link
Contributor

👍

ceedubs added a commit that referenced this pull request Oct 27, 2015
admit weaker typeclass instances for OptionT when the wrapped Functor…
@ceedubs ceedubs merged commit 3317f52 into typelevel:master Oct 27, 2015
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.

6 participants