Частичное применение параметров типа - PullRequest
13 голосов
/ 03 апреля 2011

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

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]

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

Ответы [ 5 ]

14 голосов
/ 03 апреля 2011

Вас могут заинтересовать лямбды типа.Частичное приложение, которое вы использовали в своем ответе, на самом деле реализовано в 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 голосов
/ 03 июля 2018

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

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

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


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

2 голосов
/ 03 апреля 2011

поиск в Google для «частичного применения типа». Я нашел это решение, опубликованное Джеймсом Ири в дискуссионном списке 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"
0 голосов
/ 21 апреля 2019

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

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

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])
0 голосов
/ 15 ноября 2016

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

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