Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adamgfraser
Copy link
Contributor

Resolves #4844. Adds a type alias to allow & to be used on both Scala 2 and Scala 3.

@adamgfraser adamgfraser requested a review from jdegoes March 26, 2021 15:13
@regiskuckaertz
Copy link
Member

regiskuckaertz commented Mar 26, 2021

Bloody hell that was fast 🕺 I refrained from going one step further because of the dotty compat but this would be nicer:

type &[A, B] = Has[A] with Has[B]

What do you think?

I thought about this after @kitlangton 's presentation at zio world. I think it's a great idea to get rid of the type alias boilerplate but Has[_] is 5 characters long and life is too short 😄

jdegoes
jdegoes previously approved these changes Mar 26, 2021
@kitlangton
Copy link
Member

Bloody hell that was fast 🕺 I refrained from going one step further because of the dotty compat but this would be nicer:

type &[A, B] = Has[A] with Has[B]

What do you think?

I thought about this after @kitlangton 's presentation at zio world. I think it's a great idea to get rid of the type alias boilerplate but Has[_] is 5 characters long and life is too short 😄

The following works in Dotty, but there's not much we can do in Scala 2.

type ++[A,B] <: Has[_] = (A,B) match {
  case (Has[_], Has[_]) => A & B & Has[_]
  case (_, Has[_]) => Has[A] & B
  case (Has[_], _) => A & Has[B]
  case (_,_) => Has[A] & Has[B] 
}

val layer = ZLayer.fromAuto[Console ++ String ++ Has[Int] ++ Boolean](layer, boolLayer, Console.live) 

@adamgfraser
Copy link
Contributor Author

@regiskuckaertz I think one of our lessons from ZIO 1.0 has been that hiding the Has data type doesn't pay off in the long term. It seems really nice to avoid writing Has everywhere, which is why we created the type aliases for the services. However, it creates user confusion about which date types are Has and which ones are not and leads to errors when users accidentally created nested Has data types so I think it is best to stick to the simple definition of intersection types that is the same across Scala versions.

@adamgfraser
Copy link
Contributor Author

That is really interesting regarding the match types.

@kitlangton
Copy link
Member

kitlangton commented Mar 27, 2021

While I agree it could be nice to have something like that in Scala 2:

type ++[A,B] = Has[A] with Has[B]

The problem is when you use it to join more than two types, the left hand side is now a Has and will become doubly wrapped, so you'd actually need:

type ++[A,B] = A with Has[B]

But then it's a bit weird to use, as you have to explicitly wrap the first type—or add some second operator that also wraps the lhs. Either way, not too great. Probably best for individuals to implement it themselves in their own libraries if they really want that, until we can figure out something more elegant (like that match type approach).

@adamgfraser adamgfraser requested a review from jdegoes March 27, 2021 02:49
@regiskuckaertz
Copy link
Member

regiskuckaertz commented Mar 27, 2021

type ++[A,B] <: Has[_] = (A,B) match {
  case (Has[_], Has[_]) => A & B & Has[_]
  case (_, Has[_]) => Has[A] & B
  case (Has[_], _) => A & Has[B]
  case (_,_) => Has[A] & Has[B] 
}

@kitlangton hmm, I see, at that point ++ is not a type alias but a type constructor, like *: for inductive tuples. Then the problem disappears.

@adamgfraser good point, I think this is wise.

@adamgfraser adamgfraser merged commit 9a93356 into zio:master Mar 27, 2021
@adamgfraser adamgfraser deleted the intersection branch April 6, 2021 01:22
@adamgfraser adamgfraser mentioned this pull request Nov 16, 2021
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.

with is too long

4 participants