5

kłopoty z typu "rodzaje":Rodzaje niezgodnych z typem lambda

trait Sys[ S <: Sys[S]] 
trait Expr[S <: Sys[S], A] 
trait Attr[S <: Sys[S], A[_]] 
def test[ S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ??? 

To nie z

error: kinds of the type arguments (S,[x <: Sys[x]]Expr[x,Int]) do not conform 
to the expected kinds of the type parameters (type S,type A) in trait Attr. 
[x <: Sys[x]]Expr[x,Int]'s type parameters do not match type A's expected parameters: 
type x's bounds <: Sys[x] are stricter than type _'s declared bounds >: Nothing <: Any 
      def test[S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ??? 
           ^

czym problem z deklarowanymi granicami? Czy muszę nosić ten typ częściowo pseudokrop * cr do konstruktora typu trait Attr? I dlaczego? Czy mogę to naprawić bez dotykania definicji Attr?

zrobić potrzebują granic w funkcji test w celu wdrożenie do pracy, ale robię nie chcą rozmnażać te granice do publicznego interfejsu Attr.


Uwaga: Jeśli używam typ członkiem (co nie chcę), to działa:

trait Attr[S <: Sys[S]] { type A[_]} 
def test[ S <: Sys[S]]: Attr[S] { type A[S <: Sys[S]] = Expr[S, Int]} = ??? 

Odpowiedz

4

Jak można zaobserwować, nie zawsze można niedopasowanie granic, gdy dostarczenie argumentu o wyższym typie. Co ciekawe, to jest rzeczywiście problem wariancji:

class A 
class B extends A 
trait NeedsNeedsA[T[S <: A]] 
trait NeedsNeedsB[T[S <: B]] 
trait NeedsA[S <: A] 
trait NeedsB[S <: B] 

def x: NeedsNeedsA[NeedsB] // fails 
def y: NeedsNeedsB[NeedsA] // works 

które ma sens, jeśli myślisz o wyższej kinded typu jako funkcję w sprawie rodzajów, w kontrawariantny związany jej argument jest.

Co ciekawe, w typie strukturalnym, który znajduje się na powierzchni dużo jak podtypy, Scala nie daje ten sam błąd:

def t: MemberNeedsA { type T[S <: B] } 
def u: MemberNeedsB { type T[S <: A] } 

dlatego że typ strukturalny jest coś w rodzaju skrzyżowania:

def s: MemberNeedsA with MemberNeedsB 

i może się zdarzyć, że to przecięcie w rzeczywistości nie może istnieć, ale Scala tego nie sprawdza.

OK, ale to nie jest tak istotne dla twojego pytania. Powrót do pytania: Myślę, że masz problem z wariancją. Chcesz test dać rozmówcy grzbiecie Attr, i Attr posseses funkcję typu (A[_]) i chcesz powiedzieć, toAttr posiada funkcję typu wymagającego bardziej konkretne argument. Myślę, że widzisz, dlaczego nie wolno ci tego robić - z tego samego powodu nie możesz zastąpić funkcji wymagającej bardziej konkretnego argumentu zamiast takiego, który wymagałby bardziej ogólnych argumentów.

W tym momencie obawiam się, że rozwiązanie będzie musiało być zależne od tego, co chcesz osiągnąć. Musisz dowiedzieć się, dlaczego musisz ograniczyć argument typu w niektórych przypadkach bardziej niż inne. Jeśli to sprawia, że ​​koncepcyjny sens w swoim programie, że „niektóre Attr y są bardziej restrykcyjne niż inni”, można zdefiniować:

trait Attr[S <: Sys[S], B[Y <: B[Y]], A[X <: B[X]]] 
def test[S <: Sys[S]]: Attr[S, Sys, L] = ... 

Ale rozwiązanie będzie zależeć od tego, co ograniczenie argumentu A[_] „s ma oznaczać.

+0

Dzięki za analizę. Ma to sens, chociaż "posiadanie' A [_] '" podczas gdy pozwala na wywołanie "konstruktora typu" 'A [Any]', nie można wywołać konstruktora wartości, więc pod względem czasu działania byłoby dobrze IMO. Z drugiej strony, wyobrażam sobie, że może to powodować problemy z meta-programowaniem kompilacji przy użyciu ograniczeń typu? W końcu rozwiązanie (przynajmniej tak daleko, jak go używam) jest proste. Strona użycia nie może wiele zrobić z 'A [_]' anyways, a informacje tego typu są bardziej dla osoby wywołującej 'test', więc podstawiłem' A1 = A [_] 'w' Attr' i 'test' następnie zwraca' Attr [S, Expr [S, Int]] ". –