2017-02-05 24 views
1

Учитывая этот код:Построить тип из HList по типу классов

abstract class Col[A](val name: String) 

case object Name extends Col[String]("name") 
case object Age extends Col[Int]("age") 

val cols = Name :: Age :: HNil 

type TableDef = ??? // such that `type TableDef = String :: Int :: HNil` 

Как выводит TableDef в общем виде? Я подозреваю, что это должен быть макрос, чтобы он мог принимать произвольные HListCol[_].

+0

Вы имеете какой-либо контроль над определением 'Col'? –

+0

Да, у меня есть полный контроль над 'Col'. – serega

ответ

1

Вы можете получить большую часть пути туда с shapeless.ops.Comapped,

scala> import shapeless._, ops.hlist._ 
import shapeless._ 
import ops.hlist._ 

scala> Comapped[Col[String] :: Col[Int] :: HNil, Col] 
res0: shapeless.ops.hlist.Comapped[shapeless.::[Col[String],shapeless.::[Col[Int],shapeless.HNil]],Col]{type Out = shapeless.::[String,shapeless.::[Int,shapeless.HNil]]} = [email protected] 

scala> type TableDef = res0.Out 
defined type alias TableDef 

scala> val foo: TableDef = "foo" :: 23 :: HNil 
foo: TableDef = foo :: 23 :: HNil 

scala> val foo: TableDef = "foo" :: true :: HNil 
<console>:18: error: type mismatch; 
found : shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]] 
required: TableDef 
    (which expands to) shapeless.::[String,shapeless.::[Int,shapeless.HNil]] 
     val foo: TableDef = "foo" :: true :: HNil 
           ^

Обратите внимание, что это зависит от типов элементов, имеющих Col в качестве прямого конструктора внешнего типа. Если вы хотите разместить такие типы, как Name и Age, которые скрывают Col через подтип, тогда это было бы возможно по вариации на Comapped, которая учитывает подтипы.

+0

Спасибо за указатель 'Comapped'. – serega

 Смежные вопросы

  • Нет связанных вопросов^_^