Skip to content

Conversation

@jozic
Copy link
Contributor

@jozic jozic commented Feb 15, 2018

this is another implementation of #6328 inspired by @LukaJCB and others in gitter(https://gitter.im/typelevel/general?at=5a85d126ce68c3bc748f61d4) (thanks!)

motivation: Left and Right constructors are typed as Left and Right respectively, but sometimes we want something like Option.empty which returns None but typed as Option.

The test represents a code that would not compile if plain Left/Right constructors are used

@SethTisue please check it again, thanks!
If this looks better (it does to me) then #6328 should be closed

@scala-jenkins scala-jenkins added this to the 2.13.0-M4 milestone Feb 15, 2018
*/
def left[B]: FromLeftPartiallyApplied[B] = new FromLeftPartiallyApplied[B]

private[util] final class FromLeftPartiallyApplied[B](private val dummy: Boolean = true) extends AnyVal {
Copy link

Choose a reason for hiding this comment

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

I think these dummys can now be Unit since 2.12.3 :)

Copy link
Contributor

Choose a reason for hiding this comment

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

*/
def left[B]: FromLeftPartiallyApplied[B] = new FromLeftPartiallyApplied[B]

private[util] final class FromLeftPartiallyApplied[B](private val dummy: Unit) extends AnyVal {
Copy link
Member

Choose a reason for hiding this comment

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

@why private[util] here (and 14 lines down), why not fully private? (Guess: is it because otherwise you get a warning about the type escaping...?)

Copy link
Member

Choose a reason for hiding this comment

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

are there any pros/cons to using Unit vs Boolean in this pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm pretty sure I've tried to make it fully private, but compiler wasn't happy. I will double check it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As for Unit, i guess it's just less to type, no need to give it default value. In any case it's just a trick for AnyVal.
Maybe someone has a better idea here, as I don't see much difference otherwise

Copy link
Member

Choose a reason for hiding this comment

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

I think I saw somewhere that using Unit didn't work until Scala 2.12.3. that would explain it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as expected

[error] /home/jozic/projects/github/scala/src/library/scala/util/Either.scala:468: private class FromLeftPartiallyApplied escapes its defining scope as part of type scala.util.Either.FromLeftPartiallyApplied[B]
[error]   def left[B]: FromLeftPartiallyApplied[B] = new FromLeftPartiallyApplied[B]
[error]                ^
[error] one error found
[error] (library/compile:compileIncremental) Compilation failed

if (test) Right(right) else Left(left)

/**
* Creates `FromLeftPartiallyApplied[B]` that given an argument of type `A`
Copy link
Member

Choose a reason for hiding this comment

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

Since this name appears in the Scaladoc, perhaps a shorter name could be found?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you have any good ideas? I think the name is long, but very descriptive

* //l: Either[String, Int] = Left("boo")
* }}
*/
def left[B]: FromLeftPartiallyApplied[B] = new FromLeftPartiallyApplied[B]
Copy link
Member

Choose a reason for hiding this comment

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

It's my first time seeing this pattern, so it isn't obvious to me (and might not be obvious to other reviewers) what the downsides of this pattern are. I mean, obviously it's a downside that this extra type is involved (and shows up in the Scaladoc). Are there any concealed footguns here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that was my first time as well, but it looks safe enough, except the fact you mentioned - it appears in public
like you can do Either.left[Int] and get instance of FromLeftPartiallyApplied[Int]

Copy link

Choose a reason for hiding this comment

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

I'm fairly sure there's no footguns here :)

@SethTisue
Copy link
Member

why doesn't Cats use this pattern, why does it have the #6328 version instead?

core/src/main/scala/cats/syntax/either.scala:

  def left[A, B](a: A): Either[A, B] = Left(a)
  def right[A, B](b: B): Either[A, B] = Right(b)

if this is merged, is it going to be make difficulties for Cats? (offhand, I guess you'd need separate scala-2.12 and scala-2.13 source directories to handle it...? not sure I've thought it through properly)

@LukaJCB
Copy link

LukaJCB commented Apr 25, 2018

That's a good question, though I think most cats users use the more convenient a.asLeft[A]. We could probably deprecate those in time for 2.13, I think.

@jozic
Copy link
Contributor Author

jozic commented Apr 26, 2018

I guess @LukaJCB is right, cats is full of implicits and 3.asLeft[String] is a no-brainer in Catsland, where standard lib doesn't have much of those patterns. So I'm assuming extensions like asLeft have fewer chances to be merged in std lib. Please correct me if i'm wrong here

@LukaJCB you meant deprecate def left[A, B](a: A): Either[A, B] = Left(a) and not asLeft, right? :)

@SethTisue
Copy link
Member

extensions like asLeft have fewer chances to be merged in std lib

yeah I'm not really comfortable with putting extension methods on Any

@dwijnand
Copy link
Member

dwijnand commented Jun 6, 2018

Needs a rebase, given #6681 introduced EitherTest too.

@jozic
Copy link
Contributor Author

jozic commented Jun 8, 2018

rebased on 2.13.x

@lrytz
Copy link
Member

lrytz commented Jun 8, 2018

Another approach would be adding methods to Left / Right that upcast an instance.

final case class Left[+A, +B](value: A) extends Either[A, B] {
  def up[T >: B]: Either[A, T] = this
  ...
}
scala> Left(1).up[String]
res0: scala.util.Either[Int,String] = Left(1)

@jozic
Copy link
Contributor Author

jozic commented Jun 8, 2018

@lrytz I guess that also would work
Do you want me to submit another PR with this approach and let others decide?

@lrytz
Copy link
Member

lrytz commented Jun 8, 2018

I'd say we can just discuss here. But if we go that other way, a new PR is less confusing for future us.

@adriaanm
Copy link
Contributor

adriaanm commented Aug 3, 2018

👋 what's the status here?

@jozic
Copy link
Contributor Author

jozic commented Aug 3, 2018

@adriaanm it went through all checks, and to my understanding lacks only acceptance of someone from the team (that could be you :))
@lrytz suggested another approach but so far no one commented on which one is preferred and why

@SethTisue do you have an idea what should the next step be?

@SethTisue
Copy link
Member

@jozic Lukas's suggestion is a lot simpler and on that grounds alone seems preferable to me. so yes, new PR with that, please. I'll provisionally close this one.

@SethTisue SethTisue closed this Aug 7, 2018
@SethTisue SethTisue removed this from the 2.13.0-M5 milestone Aug 7, 2018
@jozic jozic deleted the either2 branch August 7, 2018 21:18
@jozic
Copy link
Contributor Author

jozic commented Aug 7, 2018

@SethTisue new PR is #7011

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.

9 participants