-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
make all PartialApplied class AnyVal to achieve zero cost #1631
Conversation
this is great! 👍 |
If you define |
46dd6a6
to
3dbb7dc
Compare
3dbb7dc
to
d95ee44
Compare
@fthomas thanks. done |
Scala is silly sometimes 😄 I'm in favor of this change, but I think that it would be good to leave I also always forget that you can make classes package-private but still statically return their type from a public method. Should there be any concern about doing this? |
Codecov Report
@@ Coverage Diff @@
## master #1631 +/- ##
==========================================
+ Coverage 93.37% 93.37% +<.01%
==========================================
Files 240 240
Lines 3941 3942 +1
Branches 144 135 -9
==========================================
+ Hits 3680 3681 +1
Misses 261 261
Continue to review full report at Codecov.
|
@ceedubs I added the docs. As for making them package private, I couldn't think of any downside either. |
At SlamData, the
I’d also be inclined to use Finally, I think there should just be one place where this trick is documented, and maybe link to it from the use sites, because there is far more than |
To answer Q2, I guess I could not use the default argument, and instead use |
And, as you people probably already know, |
@sellout are you suggesting that we should have something like I agree that it makes sense to document this pattern somewhere and link to it in the relevant call sites. I'm fine with that either happening in this PR or creating an issue to follow up on it, since I think that this PR still represents progress and these classes weren't documented before anyway. |
@ceedubs I meant instead of private[data] final class OfPartiallyApplied[B](val dummy: Boolean = true ) extends AnyVal {
def apply[A](a: A): Const[A, B] = Const(a)
}
def of[B]: OfPartiallyApplied[B] = new OfPartiallyApplied having object of {
def apply[B]: PartiallyApplied[B] = new PartiallyApplied
private[of] final class PartiallyApplied[B](val dummy: Boolean = true) extends AnyVal {
def apply[A](a: A): Const[A, B] = Const(a)
}
} I put the tight And this isn’t a “my way is better” thing, just a “I’ve been doing it this way, and I have no idea what the tradeoffs are, and I’d generally like to do what Cats/Typelevel thinks is best” (especially if it’s documented somewhere that I am not maintaining 😄). The downside of my approach, I think, is that the Scaladoc gets even worse. Yours at least looks like a And yes – these comments are less suggestions for this PR and more that it raised questions about how we do the same thing at SlamData. So, I think my new approach is basically “do it like in Cats, except for the default argument.” I’ll update my docs, and hopefully it’ll eventually end up in some official Typelevel contributor doc. |
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.
Nice work. Would be nice if the compiler could just do this (for zero-param value classes)
docs/src/main/tut/guidelines.md
Outdated
|
||
Ops classes should be marked final and extend AnyVal, to take full advantage of inlining and prevent unnecessary allocations. | ||
|
||
The most notable exception is the case where all of the ops in the class are provided by zero-cost macros anyway, | ||
for example with Simulacrum. | ||
|
||
### <a id="partially-applied-type" href="#partially-applied-type"></a> Partially-Applied Type |
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.
Is this perhaps more accurately referred to as "partially applied type params"?
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 used the term "Partially-Applied Type" to refer to the intermediate class as a new type with type parameters partially applied. Now that I said it out loud, It's quite a mouthful. I'll change it.
docs/src/main/tut/guidelines.md
Outdated
### <a id="partially-applied-type" href="#partially-applied-type"></a> Partially-Applied Type | ||
|
||
In Scala, when there are multiple type parameters in a function, either scalac infers all type parameters or the user has to | ||
specify all of them. Often we have functions where there are one or more types that are inferable but not all of them. For example, there is helper function in `OptionT` that creates an `OptionT[A]` from an `A`. It could be written as: |
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.
s/OptionT[A]
/OptionT[F, A]
?
docs/src/main/tut/guidelines.md
Outdated
pure[List, Int](1) | ||
``` | ||
|
||
Note that the type `A` should've been given by the `a: A` argument, but since scalac cannot infer `F[_]`, user still have to specify all type params. |
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.
s/user/the user, s/have/has?
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.
Thanks @kailuowang! This is great stuff. I left a couple of very minor comments, but as soon as they are addressed I think that this is good to go.
@@ -40,7 +40,8 @@ object Const extends ConstInstances { | |||
def empty[A, B](implicit A: Monoid[A]): Const[A, B] = | |||
Const(A.empty) | |||
|
|||
final class OfPartiallyApplied[B] { | |||
/** Uses the [[http://typelevel.org/cats/guidelines.html#partially-applied-type-params Partially Applied Type Params technique]] for ergonomics. */ | |||
private[data] final class OfPartiallyApplied[B](val dummy: Boolean = true ) extends AnyVal { |
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.
Minor, unnecessarily picky comment: the alignment of the scaladoc comment is a little off here.
@@ -221,8 +221,9 @@ object Free { | |||
|
|||
/** | |||
* Pre-application of an injection to a `F[A]` value. | |||
* @param dummy is introduced solely for the sake of making this a value class and thus zero allocation cost. |
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.
Should this have the same comment with link that the other places have?
56fe374
to
b0593e4
Compare
@ceedubs comments addressed. |
ping @ceedubs again |
@kailuowang sorry for the long delay and on such trivial nitpicky comments 😲. This looks great to me! 👍 |
For posterity: the reason why the |
A trick from scalaz thanks to @edmundnoble from this comment