Определение конструктора для класса типов, который принимает метод с параметром типа?
У меня есть ситуация, когда ни одно из известных мне решений не кажется хорошим. Я пытаюсь определить класс типов, как в приведенном ниже примере, где он имеет абстрактный тип
S
который должен реализовывать другой класс типов (не показан)
Valid[A]
. Кажется, самый простой способ сделать это - создать
apply
конструктор, который заставит пользователя ввести
S
и автоматически добавить неявный экземпляр для
sIsValid
.
Проблема в том, что функция
changeType
принимает параметр типа. Несмотря на некоторые поисковые запросы, я не понял, как написать аннотацию типа для функции, которая принимает параметр типа (это может быть потому, что кажется, что Scala не позволяет анонимные функции с параметрами типа). Кажется ли мой подход здесь разумным? Если я могу предоставить аннотацию типа для
changeType
тогда пользователь класса типов все еще может передать неанонимную функцию в
apply
конструктор, который кажется наиболее удовлетворительным решением.
abstract class IsTC[A[_], T] {
// type S is an abstract type rather than type parameter, but must implement Valid[A]
type S
implicit val sIsValid: Valid[S]
def get(self: A[T], i: Int): T
def changeType[_T]: A[_T]
}
object IsTC {
def apply[A[_], T, _S](
fget: (A[T], Int) => T,
fchangeType: // what should this type annotation be?
): IsTC[A, T] { type S = _S } = new IsTC[A, T] {
type S = _S
def get(self: A[T], i: Int) = fget(self, i)
def changeType[_T]: A[_T] = fchangeType[_T]
}
}
Любая помощь / мысли с благодарностью получены.
1 ответ
Scala 2 не поддерживает полиморфные функции. Полиморфными могут быть методы, а не значения. А функции - это ценности. Полиморфные функции можно эмулировать с помощью оберток
// for [A] => (a: A) => B[A]
trait Poly {
def apply[A](a: A): B[A]
}
или же
// for [A <: U] => (a: A) => B[A]
trait Poly[U] {
def apply[A <: U](a: A): B[A]
}
нравиться shapeless.Poly
. Они обобщают обычные функции
trait Function[A, B] {
def apply(a: A): B
}
Пытаться
object IsTC {
def apply[A[_], T, _S](
fget: (A[T], Int) => T,
fchangeType: FchangeType[A]
): IsTC[A, T] { type S = _S } = new IsTC[A, T] {
override type S = _S
override implicit val sIsValid: Valid[_S] = ???
override def get(self: A[T], i: Int) = fget(self, i)
override def changeType[_T]: A[_T] = fchangeType[_T]
}
}
trait FchangeType[A[_]] {
def apply[X]: A[X]
}
Дотти имеет полиморфные функции
[A <: U] => (a: A) => f[A](a)
полиморфных типов функций
[A <: U] => A => B[A]
но есть
implementation restriction: polymorphic function types must have a value parameter
поэтому у вас не может быть полиморфного типа функции
[X] => A[X]
( не путать с лямбда-типом
[X] =>> A[X]
) на данный момент даже есть.
Также (помимо эмуляции с помощью оберток) некоторые полиморфные типы могут быть выражены через экзистенциальные типы:
[A] => B[A] => C
(для постоянного
C
) на самом деле
B[_] => C
.
Это потому что
∀a: (B(a) => C)
≡
(∃a: B(a)) => C
.