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

Typeclass instance usage convention #27

Closed
ceedubs opened this issue Feb 1, 2015 · 5 comments
Closed

Typeclass instance usage convention #27

ceedubs opened this issue Feb 1, 2015 · 5 comments

Comments

@ceedubs
Copy link
Contributor

ceedubs commented Feb 1, 2015

The two implementations are effectively identical:

implicit def OrShow1[A: Show, B: Show]: Show[A Or B] =
  Show.show[A Or B](_.fold(a => s"LOr(${Show[A].show(a)})", b => s"ROr(${Show[B].show(b)})"))

implicit def OrShow2[A, B](implicit showA: Show[A], showB: Show[B]): Show[A Or B] =
  Show.show[A Or B](_.fold(a => s"LOr(${showA.show(a)})", b => s"ROr(${showB.show(b)})"))

In order to make it easier for newcomers to contribute, I think cats should establish and document a convention for which of the two approaches to use.

Here is a proposed convention:
If your function needs to call a method on the type class instance, it should use the latter approach. This prevents the unnecessary calls to Show.apply.
If your function just needs the evidence of the type class instances so it can call through to another function that requires them, it should use the former aproach, as it is a bit cleaner.

There are also questions about whether you should use names like showA: Show[A] or ShowA: Show[A] or A: Show[A], etc. I don't really have a preference on convention here, but I think the more of this we can put into a contributor guide the less people have to worry about not knowing the right way to do it or submitting a pull request that gets nitpicked.

Thoughts?

@non
Copy link
Contributor

non commented Feb 1, 2015

I agree with pretty much all of this: I think we should prefer [A: Foo] if the Foo[A] instance is just being routed somewhere else, and (implicit xyz: Foo[A]) if method's on the xyz instance are needed (since even with @inline the Foo.apply call has overhead).

As far as the names of the evidence parameter, I know @tixxit prefers (implicit A: Foo[A]). How do folks feel about that? I often use ev but on reflection I don't think there's really a good reason -- it seems a bit cranky. I guess I don't know showA but unless there are multiple instances it seems verbose.

@non
Copy link
Contributor

non commented Feb 1, 2015

(And yes, we do need a contributor guide that spells this out.)

@fthomas
Copy link
Member

fthomas commented Feb 1, 2015

I always liked the idea to view the A in (implicit A: Foo[A]) as the companion for the type parameter. But this is only applicable as long as you only have one instance per type parameter. In the case of two or more instances I guess I'd prefer (implicit fooA: Foo[A], barA: Bar[A]).

rossabaker added a commit to rossabaker/cats that referenced this issue Feb 2, 2015
Implements feedback from typelevel#11.  Specifically:
1. LOr and ROr move to `Or.LeftOr` and `Or.RightOr`.
2. Constructors are still public, but `left` and `right` preserved in
   `OrFunctions` to infer `Or`.  Use what you like.
3. Only the Scaladoc is ripped from Scalaz.

Also tries to adhere to the emerging consensus on typelevel#27.

Preliminar benchmarking showed monomorphism is faster than polymorphism,
and that implementing other operations using fold/bimap is immeasurable.
The second finding is dubious with respect to allocations.  If someone
can prove these guilty via benchmark, we can revisit.

I'd like to add tests after typelevel#29 happens.
@julien-truffaut
Copy link
Contributor

shall we close this ticket?

@non
Copy link
Contributor

non commented Feb 5, 2015

Yes, I think we have reached broad agreement.

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

No branches or pull requests

4 participants