2012-06-14 14 views
7

Estoy tratando de usar sin forma para acumular fácilmente objetos de una manera segura.Shapeless: Prefijo. Implícito no encontrado

El problema es cuando quiero concat (:::) dos HList. Me encuentro con un problema de novato (al menos parece). Se pierde una instancia implícita Prepend en el contexto.

Sin embargo, mirando en hlist.scala, puedo ver que implicit def genérica se definen en los objetos Prepend y PrependAux.

Agregar import Prepend y import PrependAux manualmente no cambió nada (obviamente ...).

Así que aquí el código reducida al mínimo:

enter code here 

import shapeless._ 
import HList._ 
import Prepend._ 
import PrependAux._ 

object test { 

    val a:HList = 1 :: 4 :: "A" :: HNil 
    val b:HList = "R" :: false :: HNil 

    val c:HList = a ::: b // <<<<<<<<<<< NEEDS A Prepend in the context 

} 

En la consola ahora:

[error]  test.scala:10: could not find implicit value for parameter prepend: shapeless.Prepend[shapeless.HList,shapeless.HList] 
[error]  val c:HList = a ::: b // this needs an implicit Prepend in the current context 

Lo que debería quemar mis ojos?

gracias

EDITAR

Una pequeña actualización para volver a complejizar un poco el problema real, porque a la vulgarización era fuerte antes.

Aquí es el tipo de cosas que yo sería capaz de hacer:

case class A[L<:HList](a:L) { 
    def doSmth[C <:HList](c:C) = a ::: c 
} 

por lo que he no el acceso al tipo real, sólo sé que son Hlist s.

+0

las únicas respuestas han sido actualizadas también. y todavía funciona Lo que faltaba en mi solución era, al parecer, la opción scalac ... –

Respuesta

10

Los up-cast a HList son el problema aquí. No hay casi nada que puedas hacer con un simple viejo HList (aparte de agregarle nuevos elementos).

Usted puede proporcionar anotaciones de tipo más informativos:

val a: Int :: Int :: String :: HNil = 1 :: 4 :: "A" :: HNil 
val b: String :: Boolean :: HNil = "R" :: false :: HNil 
val c: Int :: Int :: String :: String :: Boolean :: HNil = a ::: b 

o simplemente dejar que se desprenden los tipos, que suele ser mucho más conveniente:

val a = 1 :: 4 :: "A" :: HNil 
val b = "R" :: false :: HNil 
val c = a ::: b 

En respuesta a tu comentario : puede hacer lo que quiera si se asegura de que tiene la evidencia que necesita (tenga en cuenta que he supuesto que a: A fue un error ortográfico para a: L, y que t Usted necesitará -Ydependent-method-types para que esto funcione):

case class A[L <: HList](a: L) { 
    def doSmth[C <: HList](c: C)(implicit p: Prepend[L, C]) = a ::: c 
} 

En general, puede simplemente mirar a los implícitos que son necesarios para las operaciones que se está usando, y luego los incluyen en su método.

+0

Thx, tienes toda la razón (así que lo validé por supuesto). En realidad, mi ejemplo ha reducido demasiado el problema.Porque mi problema reside en el tipo de cosas (un poco menos reducido): 'case class A [L <: HList] (a: A) {def doSmth [C <: HList] (c: C) = a ::: c} '. Qué piensas ? –

+0

@andypetrella: he editado para responder a su pregunta. –

+0

¡Tienes razón para el error tipográfico! Lo siento por eso. Thx para la actualización (voy a actualizar la pregunta también). En realidad lo hice, y probablemente necesité la opción de la que hablaste para que funcione. De nuevo, voy a intentarlo pronto. –