Because we have too few solutions
Library | Docs | Types | Integrations | Notes |
---|---|---|---|---|
built-in | official | AnyVal extended by class with a single value |
many libraries support AnyVal s |
- Scala 2/3, but on 3 it has a replacement - cannot always prevent boxing (unreliable) |
built-in | official | opaque type Name = Underlying |
vanilla version has no integrations | - Scala 3-only - always prevents boxing |
Scalaz (scalaz/scalaz ) |
Underlying @@ Tag |
? | - Scala 2/3 - it's a hack but works |
|
Macwire (softwaremill/macwire ) |
Underlying @@ Tag |
? | - Scala 2/3 - like Scalaz' version - only used for DI with Macwire |
|
Kebs (theiterators/kebs ) |
Underlying @@ Tag @tagged macro annotationOpaque[Underlying, Name] extended by Name companion |
a lot | - Scala 2/3 - solution for Scala 2/3 and integrations |
|
NewType (estatico/scala-newtype ) |
@newtype , @newsubtype macro annotations |
a lot, via Coercible[Underlying, Name] type class |
- Scala 2-only (macro-annotations on Scala 3 are a blocker) - a lof of integrations - macro annotation conveniently rewrites methods into extension methods |
|
ZIO Prelude (zio/zio-prelude ) |
official | Newtype[Underlying] , Subtype[Underlying] - extended by companion objects |
??? | - Scala 2/3 - requires manually defining extension methods in companion object |
supertagged for scala (rudogma/scala-supertagged ) |
Underlying @@ Tag Newtype0 , NewtypeT[Underlying] , Newtype[Underlying] and TaggedType variants - extended by companion objects |
possible, via Extractor[Underlying, Name] type class |
- Scala 2-only - requires manually defining extension methods in companion object |
|
Monix’s Newtypes (monix/newtypes ) |
official | Newtype[Underlying] , NewtypeWrapped[Underlying] , NewtypeValidated[Underlying] , NewtypeK[Underlying] , NewtypeCovariantK[Underlying] and NewSubtype[Underlying] variants - extended by companion objects |
possible, via HasExtractor.Aux[Name, Underlying] and HasBuilder.Aux[Name, Underlying] type classes |
- Scala 2/3 - requires manually defining extension methods in companion object |
neotype (kitlangton/neotype ) |
TypeWrapper[Underlying] , Newtype[Underlying] , Subtype[Underlying] - extended by companion objects |
some, via WithType[Underlying, Name] type class |
- Scala 3-only - allows validation of (some) input in compile-time - requires manually defining extension methods in companion object |
|
Yet Another Newtype Library - yantl (arturaz/yantl ) |
official | Newtype.Of[Underlying] , Newtype.ValidatedOf(...) , Newtype.WithoutValidationOf[Underlying] extended by companion object |
possible, via Newtype.WithType or Newtype.WithUnvalidatedType type classes |
- Scala 3-only - requires manually defining extension methods in companion object |
refined (fthomas/refined ) |
Underlying Refined Refinment |
a lot, via Validate type class |
- Scala 2/3 - allows compile-time validation of some values, but only on Scala 2 |
|
Iron (Iltotore/iron ) |
official | Underlying :| Refinment , RefinedTypeOps[Underlying, Refinement, OpaqueTypeName] extended by companion object |
a lot via Constraint type class |
- Scala 3-only - allows validation of (some) input in compile-time |
Refined4s (kevin-lee/refined4s ) |
official | Refined[Underlying] , NewType[Underlying] extended by companion object |
some, via mixins to companion object or deriving method in companion |
- Scala 2/3 |
I conveniently skipped detailed description for some other attempts that had few stars like:
- Newts (
sir-wabbit/newtypes
) - another Newts (
julien-truffaut/newts
) - Opaque newtypes (
indoorvivants/opaque-newtypes
) - sprout (
lorandszakacs/sprout
) - dilate (
vitorsvieira/dilate
) - Mazboot (previously called Validated) (
tabdulradi/mazboot
) - taggy (
acjay/taggy
) - as (
makiftutuncu/as
) - ...
The motivation of this list is not comparing the features of tagged/newtype/refined libraries - they 90% overlapping.
The goal is to show that instead of picking 1 solution, commiting to it, and making sure all libraries would have good integration with it, we have gazillion of half-baked solutions, none of which is perfect, each boasting about 1 thing that no-one else has, and each requiring integrating it yourself with half the libraries because only half of them have existing integrations that the author just happen to find convenient.
It is a huge waste of duplicated effort, it showcases that development in our community is ego-driven ("there is no glory in contributing to someone else library, but there is in writing it from scratch!"), and this is why we cannot have nice things.
If this comment offended you, good. It means that the message reached.