Определение конструктора для класса типов, который принимает метод с параметром типа?

У меня есть ситуация, когда ни одно из известных мне решений не кажется хорошим. Я пытаюсь определить класс типов, как в приведенном ниже примере, где он имеет абстрактный тип 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.

Другие вопросы по тегам