I am trying to use refined to create smart constructors based on primitives and avoid wrapping since same types might be used in large collections. Am I doing this right? Seems to work but a bit boilerplaty
type ONE_Pred = = MatchesRegex[W....
type ONE = String @@ ONE_Pred
type TWO_Pred = OneOf[...
type TWO = String @@ TWO_PRED
and then
case class C(one:ONE, two:TWO)
object C {
def apply(one:String, two:String):Either[String, C] =
(
refineT[ONE_Pred](one),
refineT[TWO_Pred](two)
).mapN(C.apply)
}
Refined
has a mechanism for creating a companion-like objects that have some utilites already defined:
type ONE = String @@ MatchesRegex["\\d+"]
object ONE extends RefinedTypeOps[ONE, String]
Note that:
type ONE
.You get:
ONE("literal")
as alternative to refineMT
/refineMV
ONE.from(string)
as alternative to refineT
/refineV
ONE.unapply
so you can do string match { case ONE(taggedValue) => ... }
ONE.unsafeFrom
for when your only option is to throw an exception.With these "companions", it's possible to write much simpler code with no need to mention any predicate types:
object C {
def apply(one: String, two: String): Either[String, C] =
(ONE.from(one), TWO.from(two)).mapN(C.apply)
}
(example in scastie, using 2.13 with native literal types)