Improve opaque types

Its author moved on before it was ready to be integrated and maintained by other people, and no one picked it up.

In Scala 2, the following code will not box any of the integers, AFAIK (someone correct me if I’m wrong):

List((0, 1), (2, 3), (4, 5)).foreach(x => useAnInt(x._1 + x._2))

In the current implementation of Scala 3, the tuples will box the integers they hold, and the function passed to foreach will have to unbox them before adding them up.

6 Likes

You’re not wrong. If you javap -c it you’ll see that Scala 2 uses Tuple2$mcII$sp (specialized) throughout, rather than an ordinary Tuple2, to avoid boxing the Ints. Whereas Scala 3 boxes them.

2 Likes

Is the art of writing one’s application as a set of libraries totally lost? :frowning:

^ was a jokey comment to address a serious issue: Adding a burden for library writers is actually harming the ecosystem enormously… it requires a lot more time and resources for library writers/publishers to keep up. Cross compilation/special rules, etc. only adds to that.

2 Likes

Now that inline def works on opaque types. Do we need those specialised classes for primitives types anymore, @gvolpe? This should be enough I think?

trait NewType[Wrapped]:
  opaque type Type = Wrapped
  inline def apply(w: Wrapped): Type = w
  extension (t: Type) inline def value: Wrapped = t
  given (using CanEqual[Wrapped, Wrapped]): CanEqual[Type, Type] = CanEqual.derived
3 Likes

Two and a half years after this thread went quiet, and from my POV opaque type remains significantly less easy to use than Haskell’s newtype.

Haskell gives you a nicely-made box to put your data in, while Scala gives you a flatpack and a screwdriver and insists that’s just as good :expressionless:

Re-reading this thread I think @gvolpe provided an accurate description of where Scala’s limitations are, but his proposals seemed to fly into a wall of opposition.

One thing I’d add to the ask is the ability to auto-derive arbitrary type-class instances by delegation to the underlying type, as in GeneralizedNewtypeDeriving:

newtype Dollars = Dollars { getDollars :: Int } deriving (Eq,Show,Num)

How many lines of code does it take to express the above in Scala atm?

3 Likes

I think it should be possible to implement deriving on an opaque type, the issue is that because opaque types are so flexible, what would the deriving clause desugar to? One idea I had was that it still desugars to e.g. Show.derived in the companion, but then we provide the user factory methods to select which kind of mirror they should provide for an opaque type.