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

Add Reducible for Eval and Id #1475

Merged
merged 2 commits into from
Jan 3, 2017
Merged

Add Reducible for Eval and Id #1475

merged 2 commits into from
Jan 3, 2017

Conversation

johnynek
Copy link
Contributor

Using these on their own may not be that useful, but Reducible composes, so this allows us to use a reducible on F[Eval[T]], Eval[F[T]] or F[Id[T]], Id[F[T]].

One small nice win is that size on Eval can avoid evaluation entirely. Probably never a win in practice, but hey...

@@ -310,6 +310,30 @@ private[cats] trait EvalInstances extends EvalInstances0 {
}
}

implicit val catsReducibleForEval: Reducible[Eval] =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

should this be combined with the monad/comonad above?

I don't think we can ever implement Traverse[Eval] (I'd love to be wrong about that), so it didn't have the same ambiguous implicit concern that Id has (since Traverse[Id] also extends Foldable[Id], we don't want Reducible[Id] we have to either use priority, or unify them in the same instance).

Copy link
Contributor

Choose a reason for hiding this comment

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

Couldn't a fairly trivial Traverse[Eval] be implemented where traverse looks something like this?

def traverse[G[_]: Applicative, A, B](fa: Eval[A])(f: A => G[B]): G[Eval[B]] =
  f(fa.value).map(Eval.now)

It's a bit wonky, but the Comonad, Reducible, etc instances are already based on eager calls to .value, so I don't know if it's any different.

Copy link
Contributor

Choose a reason for hiding this comment

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

It occurs to me that such a Traverse instance can be defined for any comonad, so it it's probably a known thing with some known properties to people who know more than I do :)

Copy link
Contributor

Choose a reason for hiding this comment

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

It also occurs to me that a big difference between this Traverse instance and the instances that you've added is that yours shouldn't ever lead to stack overflows while this one is probably pretty likely to bite people with them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

none of our instances call .value unless the return type requires it. It seems to me we should keep that since otherwise you lose the stack safety if Eval, so that is what I really meant. If you are willing to call .value, Eval is isomorphic to Id I think, but the best practice of Eval (though perhaps not required, but the real rule might somewhat complex and difficult to verify) is to only call .value once at the end.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that limiting ourselves to instances that (if they need to call .value at all) only call .value once at the end is probably a good general rule. 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm sorry for all of the thinking out loud here, but I just realized that the traverse implementation above only calls .value once, just as the Reducible instances do. Is there a reason that we would consider this to be different? Maybe because the Eval in the return type suggests that we aren't calling .value?

@johnynek
Copy link
Contributor Author

hit the flakey future test. Restarted.

@johnynek
Copy link
Contributor Author

We could add Reducible for Function0 also.

@codecov-io
Copy link

codecov-io commented Nov 25, 2016

Current coverage is 92.24% (diff: 96.87%)

Merging #1475 into master will increase coverage by <.01%

@@             master      #1475   diff @@
==========================================
  Files           242        246     +4   
  Lines          3619       3802   +183   
  Methods        3549       3683   +134   
  Messages          0          0          
  Branches         70        119    +49   
==========================================
+ Hits           3338       3507   +169   
- Misses          281        295    +14   
  Partials          0          0          

Powered by Codecov. Last update e20cb6b...544bfc1

@johnynek
Copy link
Contributor Author

This many test misses would indicate Reducible and Foldable laws don't exercise all the functions.

@non
Copy link
Contributor

non commented Nov 28, 2016

@johnynek Yeah it seems like we need more of those. Do you mind adding some to the PR?

I'm 👍 on this addition, BTW.

@johnynek
Copy link
Contributor Author

added some more laws to improve coverage. Should be good now.

I'm especially keen on the Reducible[Eval] since I think composing that will be somewhat useful.

@ceedubs
Copy link
Contributor

ceedubs commented Dec 22, 2016

Thanks @johnynek! I remember thinking about adding Reducible[Id] at some point and I can't remember why I didn't pursue that further.

I've left #1475 (comment) which we may want to make a conscious decision about before merging this.

@ceedubs
Copy link
Contributor

ceedubs commented Dec 22, 2016

👍

@non would you consider this good to merge?

I think that any instances that we've defined for Eval we should probably be able to to define for Function0 as well.

@johnynek
Copy link
Contributor Author

johnynek commented Dec 29, 2016 via email

@johnynek johnynek mentioned this pull request Dec 30, 2016
11 tasks
@johnynek
Copy link
Contributor Author

This seems to have 2 👍 unless I'm mistaken. @non gave a +1 early, would you (or someone else) like to look again before we merge for 0.9.0?

@non
Copy link
Contributor

non commented Jan 3, 2017

Yes! 👍

@johnynek johnynek merged commit 822a2fe into master Jan 3, 2017
@johnynek johnynek deleted the oscar/reducible-eval-id branch January 3, 2017 17:45
@stew stew removed the in progress label Jan 3, 2017
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