2016-09-14 9 views
2

Я пытаюсь найти способ избежать потери информации о типе в возвращаемом значении для моего метода.Избегайте потери информации о типе в возвращаемом значении

У меня есть следующие:

val defs0 = Default.mkDefault[Person, Some[String] :: Some[Int] :: HNil](Some("odd") :: Some(42) :: HNil) 

Использование IntelliJs «Добавить аннотацию типа» дает тип:

Default.Aux[Person, ::[Some[String], ::[Some[Int], HNil]]] 

Это нормально, за исключением того, что я не хочу, чтобы указать поля Person, когда я вызовите mkDefault. Так что я создал это:

object MkDefault { 
    object toSome extends Poly1 { 
    implicit def default[P] = at[P](Some(_)) 
    } 

    def apply[P, L <: HList, D <: HList] 
    (p: P) 
    (implicit 
    lg: LabelledGeneric.Aux[P, L], 
    mpr: Mapper.Aux[toSome.type, L, D] 
): Default.Aux[P, D] = 
    Default.mkDefault[P, D](mpr(lg.to(p))) 
} 

Теперь я могу сделать:

val defs1 = MkDefault(Person("odd", 42)) 

это хорошо, за исключением предполагаемого типа из IntellJ выглядит следующим образом:

Default.Aux[Person, HNil] 

Как я могу сделать выведенный тип defs1 равен выведенному типу defs0?

* без указания полей класса Person

+0

Используйте 'mpr.Out' как тип вывода вместо' d' – dk14

ответ

2

Использование mpr.Out вместо D как тип выхода:

object MkDefault { 
    object toSome extends Poly1 { 
    implicit def default[P] = at[P](Some(_)) 
    } 

    def apply[P, L <: HList, D <: HList] 
    (p: P) 
    (implicit 
    lg: LabelledGeneric.Aux[P, L], 
    mpr: Mapper.Aux[toSome.type, L, D] 
): Default.Aux[P, mpr.Out] = 
    Default.mkDefault[P, D](mpr(lg.to(p))) 
} 

Пример:

scala> val defs1 = MkDefault(Person("odd", 42)) 
defs1: shapeless.Default[Person]{type Out = shapeless.::[Some[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String]],shapeless.::[Some[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("age")],Int]],shapeless.HNil]]} = [email protected] 

P.S.

Если вы не возражаете Option вместо Some, вы можете также использовать AsOptions

val opt = Default.AsOptions[Person] 
val def3 = Default.mkDefault[Person, opt.Out](Some("aaa") :: Some(5) :: HNil) 

Проверить:

scala> implicitly[def3.Out =:= ::[Option[String], ::[Option[Int], HNil]]] 
res12: =:=[def3.Out,shapeless.::[Option[String],shapeless.::[Option[Int],shapeless.HNil]]] = <function1> 
+0

Удивительный, спасибо! Однако, чтобы получить _exact_ того же типа, мне нужно было использовать Generic вместо LabelledGeneric. Не нашел бы это без вашего ответа, хотя, отмечая, как принято :) – eirirlar

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

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