Ограничение родственных типов для аргумента Function1 и типа результата - PullRequest
2 голосов
/ 16 января 2012

Учитывая некоторые типы с более высоким родом:

trait Impl [S]
trait Event[S, A]
trait Key  [A]

Как я могу переписать следующее определение:

def declare[A](fun: Impl[_] => Event[_, A]): Key[A] = ???

, чтобы аргумент fun действительно был Impl[S] => Event[S, A] для некоторых S.Например, в следующем случае:

trait Impl[S] { def ev1: Event[S, Int]; def ev2: Event[T, Int] }

Это будет действительный вызов:

declare(_.ev1)

, но это не так:

declare(_.ev2)  // this currently compiles

РЕДАКТИРОВАТЬ

Вот более полный пример, который точно показывает, почему я сталкиваюсь с проблемами:

trait Sys  [S <: Sys[S]]
trait Event[S <: Sys[S], A, Repr]

trait Decl {
  type Impl[S <: Sys[S]]

  protected def declare[U](fun: Impl[_] => Event[_, U, Impl[_]]): Unit = ???
}

Следующее событие, объявляющее объект-компаньон, не компилируется:

object Test extends Decl {
  type Impl[S <: Sys[S]] = Test[S]

  case class Renamed(name: String)

  declare[Renamed](_.renamed)
}

trait Test[S <: Sys[ S]] {
  def renamed: Event[S, Test.Renamed, Test[S]]
}

из-за некоторой проблемы с сопоставлением типов:

error: type mismatch;
 found   : Event[_$1,Test.Renamed,Test[_$1]] where type _$1
 required: Event[_, Test.Renamed, Test.Impl[_]]
Note: _$1 <: Any, but trait Event is invariant in type S.
You may wish to define S as +S instead. (SLS 4.5)
Note: Test[_$1] <: Test[_], but trait Event is invariant in type Repr.
You may wish to define Repr as +Repr instead. (SLS 4.5)
          declare[ Renamed ]( _.renamed )
                                ^

Если я изменю тип функции на Impl[_] => Event[_, U, _], она компилируется, но я действительно хотел бы восстановить некоторую безопасность типов.

1 Ответ

1 голос
/ 16 января 2012

Кажется, проблема в том, что экзистенциальный тип не может быть задан с синтаксисом 'nice' Function1:

// error: not found: type S
def declare[A](fun: Impl[S] => Event[S, A] forSome { type S }): Key[A] = ???

... но он работает при использовании обычного синтаксиса:

// yes!
def declare[A](fun: Function1[Impl[S], Event[S, A]] forSome { type S }): Key[A] = ???

РЕДАКТИРОВАТЬ

К сожалению, теперь мой замечательный сайт пользуется

missing parameter type for expanded function ((x$1) => x$1.renamed)
[error]    declare[ Renamed ]( _.renamed )

Так что я должен придерживаться небезопасной версии :-(

Полагаю, мне нужна новая функция, такая как (Impl[S] => Event[S, A]) forAny { type S } ...

...