Подтвердить что ты не робот

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

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

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". как это сделать?

4b9b3361

Ответ 1

Вам может быть интересен тип lambdas. Частичное приложение, которое вы использовали в своем ответе, на самом деле реализовано в scalaz. Поскольку код, как правило, становится менее читаемым, но вместо этого они начали использовать тип lambdas. Тип, о котором идет речь, может быть записан как

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

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

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

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

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

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

Ответ 2

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

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

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

EDIT:

Это не выполняется с ковариацией в 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"

Ответ 3

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

addCompilerPlugin ("org.spire-math" %% "kind-Проектор"% "0.9.7")

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


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

Ответ 4

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

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]
}

Ответ 5

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

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

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])