Предположим, что у меня есть некоторая черта Foo
, например:
trait Foo {
def bar: List[Int]
def baz(i: Int): Unit
}
Я хочу во время компиляции установить, что все входные данные, переданные в baz
, были ранее произведены bar
.Например, если это реализация Foo
:
object A extends Foo {
def bar = List(2, 3, 5, 7)
def baz(i: Int): Unit = {
if (bar contains i) println("ok")
else println("not good")
}
}
, то я хочу обеспечить, чтобы в baz
передавались только однозначные простые числа.Это, очевидно, не работает, если известно, что тип ввода baz
равен Int
, потому что это позволяет мне создавать экземпляры всех видов целых чисел, которые не являются простыми и не находятся между 0
и 9
:
val okValues: List[Int] = A.bar
A.baz(okValues(1)) // ok
A.baz(3) // ok (but dangerous! `3` appeared out of nowhere!)
A.baz(42) // not good
Как я могу обеспечить, чтобы только значения, ранее созданные bar
, могли быть переданы в baz
?
Что не работает
Преобразование Int
в элемент типа Foo
не помогает, потому что он реализован для конкретного типа Int
в реализации A
из Foo
:
trait Foo {
type T
def bar: List[T]
def baz(t: T): Unit
}
object A extends Foo {
type T = Int
def bar = List(2, 3, 4, 5)
def baz(i: Int): Unit = {
if (bar contains i) println("ok")
else println("not good")
}
}
A.baz(42) // not good