Skip to content

Change forEffect/followedBy to productL/productR - #2083

Merged
LukaJCB merged 18 commits into
typelevel:masterfrom
Jacoby6000:#1983
Dec 15, 2017
Merged

Change forEffect/followedBy to productL/productR#2083
LukaJCB merged 18 commits into
typelevel:masterfrom
Jacoby6000:#1983

Conversation

@Jacoby6000

@Jacoby6000 Jacoby6000 commented Dec 8, 2017

Copy link
Copy Markdown
Contributor

This should resolve #1983.

I picked apL and apR based on discussion in that issue.

The deprecation caused scalac to complain about the code generated by simulacrum, so I moved the deprecated method aliases in to syntax.apply.

@emilypi emilypi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM

@Jacoby6000

Copy link
Copy Markdown
Contributor Author

Just realized I missed a bunch of other methods. working on that.

@kailuowang kailuowang added this to the 1.0.0 milestone Dec 8, 2017
@kailuowang

Copy link
Copy Markdown
Contributor

Thanks! @Jacoby6000, a scalafix migration would be handy. Let me know if you are interested in giving it a try or I can add it in a follow-up PR. Here is a good example for such rename migrations.

@kailuowang

Copy link
Copy Markdown
Contributor

also, we won't have RC2, so all the deprecation note should be 1.0.0

@Jacoby6000

Jacoby6000 commented Dec 8, 2017

Copy link
Copy Markdown
Contributor Author

@kailuowang I built the scalafix stuff, but it seems to cause some problems. forEffect and followedBy were introduced during 1.0.0, and I'm not sure how to split up the fix migrations. I've pushed my scalafix work in to #2083-scalafix.

@kailuowang

Copy link
Copy Markdown
Contributor

The problem is that the Scalafix test depends on 0.9 right? I would say for this PR we simply don't test this migration. It should be low risk

@ceedubs

ceedubs commented Dec 9, 2017

Copy link
Copy Markdown
Contributor

👍 once there is resolution on the scalafix rules.

I don't think that any word-based name is going to be perfect, but apL and apR seem less likely to cause confusion with certain effect types.

@Jacoby6000

Copy link
Copy Markdown
Contributor Author

I've added in the scalafix stuff that I drafted. I can't test it, so please look it over 😅

@kailuowang

kailuowang commented Dec 10, 2017

Copy link
Copy Markdown
Contributor

for the scalafix stuff, if you include the input and output they will be compiled, which fails due to mis-dependency as we discussed earlier. Sorry I wasn't clear, by "don't test" I mean we shouldn't include them in the input and output of the scalafix tests. Also bin compact check failed, need to add mima exceptions ( you can check CI log to see which ones are needed, or you can leave that to us).

@kailuowang
kailuowang requested a review from johnynek December 13, 2017 15:28
@Qi77Qi

Qi77Qi commented Dec 13, 2017

Copy link
Copy Markdown

Think faq page needs to be updated as well?

@kailuowang

Copy link
Copy Markdown
Contributor

close and reopen to trigger build

@LukaJCB LukaJCB closed this Dec 14, 2017
@LukaJCB LukaJCB reopened this Dec 14, 2017
LukaJCB
LukaJCB previously approved these changes Dec 14, 2017
@johnynek

Copy link
Copy Markdown
Contributor

I’m -1 on apL and apR the more I think about it. Note we already have ap. And these new methods are not that similar. I would say productR and productL are much better.

@kailuowang

kailuowang commented Dec 14, 2017

Copy link
Copy Markdown
Contributor

I am fine with productR and productL, but if people can't agree on it soon, I would propose we give up on bikeshedding this one and just leave as is (closing this PR).

@Jacoby6000

Jacoby6000 commented Dec 14, 2017

Copy link
Copy Markdown
Contributor Author

I'm not much of a fan of productL and productR, mainly because I don't really like product, either. To me, product intuitively means tuple.. So, that method makes me think a -> b -> (a, b), not f a -> f b -> f (a, b). Additionally product does not really convey the application of effects and the standard lib also has a product method which interferes.

As for the methods not being related, I think their relationship becomes more clear if you define map2 more traditionally, and then apL/apR in terms of that.

As an aside, product should probably be rewritten in terms of map2, not the other way around as it is now.

def apL[F[_]: Apply, A, B](fa: F[A])(fb: F[B]): F[A] =
  map2(fa, fb)((a, _) => a)

def apR[F[_]: Apply, A, B](fa: F[A])(fb: F[B]): F[B] =
  map2(fa, fb)((_, b) => b)

def map2[F[_], A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C)(implicit F: Apply[F]): F[C] = 
  F.ap(F.map(fa)(a => (b: B) => f(a, b)))(fb)

@Jacoby6000

Jacoby6000 commented Dec 14, 2017

Copy link
Copy Markdown
Contributor Author

I'm willing to submit and change it to productL and productR to appease the community; I only ever use the proper notation anyway.

@Jacoby6000

Jacoby6000 commented Dec 14, 2017

Copy link
Copy Markdown
Contributor Author

Going deeper in to the relationship, and why I think apL and apR are better than productL and productR:

  • <*> is ap.
  • *> is apR which applies both effects, as ap does, but only retains the value on the right.
  • <* is apL which applies both effects, as ap does, but only retains the value on the left.

I think having names which are as analagous as the symbols does a great deal towards teaching the notation. If people never use <*> or *> or <*, but instead opt for ap, apR, and apL, they will be better off whenever they move to a system using more traditional notation (like, if they learn haskell for instance). Once they realize that <*> is ap, the understanding of *> and <* will come more easily, and vice versa.

@johnynek

Copy link
Copy Markdown
Contributor

I agree with some of what you say, I feel like you are overlooking that ap is dealing with a A => B at some point: F[A => B] <*> F[A]: F[B]. The name is related to apply which is about (A => B) apply A: B. So, keeping ap about apply from A => B when there is no function in sight, to me is a bad name.

I hear you that you don't like product, but that is the name we have for F[A], F[B] => F[(A, B)]. To me, the types there are much closer to what we have at hand.

If you don't like them, I'm pretty happy to keep the current names since I think as long as names don't mislead (and I feel apR and apL do), I don't think they matter too much, so forEffect is just a pointer to the docs which often has a good mnemonic. To me, that's fine.

@Jacoby6000

Copy link
Copy Markdown
Contributor Author

I'm going to update this PR to use productL and productR, specifically because cats already has product (which I have said before). Ultimately my agreement is of little consequence. Besides that, just about anything is better than what is there currently.

@kailuowang

kailuowang commented Dec 14, 2017

Copy link
Copy Markdown
Contributor

@Jacoby6000 thanks very much! Hate to ask you one more thing, we ended up deciding that we are going to have a quick 1.0.0-RC2 release, so if it's easy for you, would you update the deprecate versions? I'd be happy to change those for you if you don't have the time.

@Jacoby6000

Copy link
Copy Markdown
Contributor Author

I'll have time in a few hours, if it can wait.

johnynek
johnynek previously approved these changes Dec 15, 2017
@Jacoby6000 Jacoby6000 changed the title Change forEffect/followedBy to apL/apR Change forEffect/followedBy to productL/productR Dec 15, 2017
Comment thread core/src/main/scala/cats/Apply.scala Outdated
*/
def map2[A, B, Z](fa: F[A], fb: F[B])(f: (A, B) => Z): F[Z] =
map(product(fa, fb)) { case (a, b) => f(a, b) }
ap(map(fa)(a => (b: B) => f(a, b)))(fb)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a sensible improvement if we only consider the default implementation, but many instances overrides product for better performance. So we might want to keep the original implementation of product and map2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

actually the law is broken with Const instance which overrides product

ConstSuite:
[info]
[info] - Apply[Const[NonEmptyList[String], Int]].apply.map2/product-map consistency *** FAILED ***
[info] GeneratorDrivenPropertyCheckFailedException was thrown during property evaluation.
[info] (Discipline.scala:14)
[info] Falsified after 3 successful property evaluations.
[info] Location: (Discipline.scala:14)
[info] Occurred when passed generated values (
[info] arg0 = Const(NonEmptyList(ꙫ, 鰓)),
[info] arg1 = Const(NonEmptyList(, )),
[info] arg2 =
[info] )
[info] Label of failing property:
[info] Expected: Const(NonEmptyList(, , ꙫ, 鰓))
[info] Received: Const(NonEmptyList(ꙫ, 鰓, , ))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah Yeah, that was a bit short sighted of me. I didn't consider overrides.

@kailuowang

Copy link
Copy Markdown
Contributor

Thanks very much! @Jacoby6000

@LukaJCB

LukaJCB commented Dec 15, 2017

Copy link
Copy Markdown
Member

Yes, thanks a lot, Jacob! :)

@LukaJCB
LukaJCB merged commit 8120890 into typelevel:master Dec 15, 2017
"_root_.cats.NonEmptyParallel.parFollowedBy." -> "parApR",
"_root_.cats.FlatMap.forEffectEval." -> "apLEval",
"_root_.cats.FlatMap.followedByEval." -> "apREval",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These rewrite rules still need to be updated to productR/productL, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah yep, they sure do. I missed those.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

fix submitted #2117

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rename followedBy and effectFor

10 participants