Частично применяя параметры типа

Я отчаянно пытаюсь решить следующее:

trait Access[Res[_]] { def access[C]: Res[C] }

trait CList[C1, A] extends Access[CList[_, A]] // ?!

def test[C1, C2, A](c: CList[C1, A]): CList[C2, A] = c.access[C2]

scalac просто говорит: "error: illegal cyclic reference involving trait CList". как я могу сделать это скомпилировать?


person 0__    schedule 03.04.2011    source источник


Ответы (5)


Вас могут заинтересовать лямбда-выражения типов. Частичное приложение, которое вы использовали в своем ответе, на самом деле реализовано в scalaz< /а>. Однако, поскольку код становится менее читаемым, вместо этого они начали использовать лямбда-выражения типов. Рассматриваемый тип может быть записан как

({type λ[α] = CList[α,A]})#λ

Это работает путем создания проекции типа на параметризованный тип λ внутри структурного типа, таким образом захватывая параметр внешнего типа (в данном случае A).

Другую проблему, связанную с дисперсией, описанную в вашем ответе, можно решить, сделав параметр Res в ковариантном Access.

После этих изменений ваш код должен выглядеть так:

trait Access[+Res[_]] { def access[C] : Res[C]}

trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ]
person Moritz    schedule 03.04.2011

погуглив «приложение частичного типа», я нашел это решение, опубликованное Джеймсом Айри в списке дебатов scala ( http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html ; изменен порядок аргументов) :

type Partial2[T[_,_], B] = {
   type Apply[A] = T[A,B]
}
trait CList[C1, A] extends Access[Partial2[CList, A]#Apply]

сыр Луиза, это действительно единственный способ сделать это в scala в 2011 году?!!

ИЗМЕНИТЬ:

Это не удается с ковариацией в A :,-(

trait Access[Res[_]] { def access[C]: Res[C] }

type Partial2[T[_,_], B] = {
  type Apply[A] = T[A,B]
}
trait CList[C1, +A] extends Access[Partial2[CList, A]#Apply]

"covariant type A occurs in invariant position"
person 0__    schedule 03.04.2011

Просто для обновления добавьте этот подключаемый модуль компилятора в свой sbt для доброй проекции, и вы получите хороший синтаксис, используя ?.
Это удаляет шаблон проецирования шрифта, который выглядит беспорядочно!
Таким образом, вы можете писать такие вещи, как Either[String, ?]

addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.7")

он реализован с той же проекцией старого типа внизу


Вы также можете найти его здесь:
https://underscore.io/blog/posts/2016/12/05/type-lambdas.html

person Danny Mor    schedule 03.07.2018

Я знаю, что это действительно старый вопрос, но в любом случае:

trait AnyAccess {
  type Res[X]
  def access[Z]: Res[Z]
}

trait AnyCList extends AnyAccess { me =>
  type C
  type A
  // this could be a subtype bound instead, if needed
  type Res[X] = AnyCList { type C = X; type A = me.A }
}
case object AnyCList {
  type of[C0, +A0] = AnyCList { type C = C0; type A <: A0 }
}

case object buh {

  def test[C1, C2, A](c: AnyCList.of[C1, A]): AnyCList.of[C2, A] = c.access[C2]
}
person Eduardo Pareja Tobes    schedule 15.11.2016

Вот метод, который сработал для меня, чтобы «частично применить параметры типа»:

У меня была такая функция, как

def foo[A, B, C, D, E](...)

Так что мне нужно было указать только один параметр типа, чтобы компилятор мог вывести остальные. Это сработало для меня:

object InferType {
  type InferType[A] = Option[A]
  def apply[A]: Option[A] = None
}

Обновите foo, чтобы он принимал дополнительный параметр типа InferType:

// t parameter is unused in implementation but
// is used by compiler to infer other type parameters
def foo[A, B, C, D, E](..., t: InferType[D]) 

Использование:

foo(..., InferType[ConcreteD])
person Ryan Berckmans    schedule 21.04.2019