2012-01-02 19 views
6

Quiero relajar las restricciones en un parámetro de tipo de rasgo y en su lugar imponerlas en un método en forma de un parámetro de evidencia. Teniendo en cuenta algún tipo de configuración esquelética:Intercambio del límite superior de un parámetro de tipo para un parámetro de evidencia

trait State[Repr] 
object Observer { 
    def apply[Repr <: State[Repr]](reader: Reader[Repr]): Observer[Repr] = 
    new Observer[Repr] {} 
} 
trait Observer[A] 
trait Reader [A] 

Esto funciona:

trait StateX[Repr <: StateX[Repr]] extends State[Repr] { 
    protected def reader: Reader[Repr] 
    def observe: Observer[Repr] = Observer(reader) 
} 

Y esto no es así:

trait StateY[Repr] extends State[Repr] { 
    protected def reader: Reader[Repr] 
    def observe(implicit ev: Repr <:< State[Repr]): Observer[Repr] = Observer(reader) 
} 

Con "inferred type arguments [Repr] do not conform to method apply's type parameter bounds [Repr <: State[Repr]]" mensaje. Dado que la evidencia ev sugiere esta conformación, me pregunto cómo se puede reparar StateY.

Respuesta

6

Su problema es que a pesar de la evidencia de la forma A <:< B implica que un valor de tipo A se puede convertir en un valor de tipo B no implica A <: B ... de hecho, la razón principal para el uso de una restricción de tipo o un límite de vista en lugar de un límite de tipo ordinario es precisamente porque tal relación de subtipo no se cumple.

consecuencia la restricción en StateY, Repr <:< State[Repr], no es suficiente para satisfacer la Repr <: State[Repr] unido en apply método Observer 's. Dado que desea relajar la restricción en el parámetro de tipo StateX, su única opción es debilitar la restricción en el parámetro de tipo del método apply correspondiente. Que le consigue algo como lo siguiente usando una vista con destino en lugar de un tipo ordinario con destino,

object Observer { 
    def apply[Repr <% State[Repr]](reader : Reader[Repr]) : Observer[Repr] = 
    new Observer[Repr] {} 
} 

o, alternativamente,

object Observer { 
    def apply[Repr](reader : Reader[Repr]) 
       (implicit ev : Repr <:< State[Repr]) : Observer[Repr] = 
    new Observer[Repr] {} 
} 

si usted prefiere utilizar restricciones en todas partes.

5

La evidencia sugiere que un Repr se puede convertir a State[Repr]. No dice nada sobre lo que se puede hacer con un Reader [Repr].

No hay un método general (independiente de T) para convertir T [A] en T [B] dado un A => B. Eso podría ser posible para una T covariante, pero no existe tal cosa en el lenguaje .

Cuestiones relacionadas