Я использую ADT, которые можно создать только после этапа проверки (что является обычной практикой в FP для обеспечения правильности). В качестве примера я использую тип Score
поверх Double
, который проверяет, что его значение в оболочке находится в пределах [0.0, 100.0].
Так у меня что-то вроде этого:
case class Score private(raw: Double) extends AnyVal
object Score {
def mk(raw: Double) = (0 <= raw && raw <= 100) option new Score(raw)
// XXX: WOULD LIKE TO GET RID OF THIS LINE:
def apply(raw: Double)(implicit ev: DummyImplicit): Score = ???
}
Это обходной путь к невозможности скрыть автоматически созданный сопутствующий класс case apply
, взятый из этого ответа https://stackoverflow.com/a/5736428/247623 на совершенно не связанный с этим вопрос.
Несмотря на то, что он работает в удовлетворительной степени - за исключением ошибки компиляции ambiguous reference to overloaded definition
совершенно бесполезной - у него есть огромный недостаток определения каждого ADT с защищенным конструктором, который должен явно определять это:
def apply(raw: Double)(implicit ev: Nothing): Score = notAllowed
Я безуспешно пробовал использовать наследование.
Можно ли вообще добиться этого с помощью макросов или макросы Scala в настоящее время не поддерживают добавление методов к классу / объекту? Что-то типа:
case class Score private(raw: Double) extends AnyVal
@guarded object Score {
def mk(raw: Double) = (0 <= raw && raw <= 100) option new Score(raw)
}
...или похожие.