zio / zio-prelude

A lightweight, distinctly Scala take on functional abstractions, with tight ZIO integration
https://zio.dev/zio-prelude
Apache License 2.0
451 stars 115 forks source link

A different encoding for Id and Const #601

Open roald-di opened 3 years ago

roald-di commented 3 years ago

First of all, as a disclaimer, I have to say that I'm fairly new to scala so please be gentle!

This is as much a question as it is a proposal.

While learning scala over the past year I have come across two different encodings for the Id type which seem to have opposite pros and cons.

The first is just type Id[+A] = A as seen in scalaz and cats.

The other is some variation on the newtype pattern as used in zio.prelude.

But I have never seen the following used or discussed:

type Id[+A] >: A <: A

object Id:
    given Covariant[Id] with
        def map[A, B](f: A => B): Id[A] => Id[B] = f

summon[Covariant[Id]] // works!

As far as I can tell this works great with implicits and doesn't need any wrapping or unwrapping.

I understand that >: A <: A and = A really mean the same thing but they seem to be consistently treated as if they were different by the compiler (in scala 2 as well).

I've used this for a while now and can't see anything wrong with it but I'm suspicious.

So is this a good idea or not?

adamgfraser commented 3 years ago

I don't have a particularly strong feeling about this. I think ideally users shouldn't really have to interact with Id directly and it should just be used to implement different operators. If you want to try it with the ZIO Prelude code base and see if it works that would be great!

roald-di commented 3 years ago

I just tried it and it has been very informative, at least now I know why no one was using it.

There are two problems that break this in scala 2.

The first is that the type argument can't be made covariant, it complains that covariant type A occurs in contravariant position, this has been fixed in scala 2.13.5.

The other is that Id[Id[A]] won't compile with cyclic aliasing or subtyping involving type Id which unfortunately means that flatten can't be implemented.

Everything works in scala 3 though, so maybe we can talk about this again in the far future when you can drop scala 2 support :)

sideeffffect commented 3 years ago

But don't get discouraged @roald-di , we're always welcoming to new contributors and there's still sooo much cool stuff to work on in ZIO Prelude. You can have a look at https://github.com/zio/zio-prelude/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%23ziohackathon or any other open ticket to take inspiration. Or anything else you may think would be a useful addition to the next generation FP-library for Scala :wink: