2017-10-04 4 views
1

J'ai écrit ce codePas en mesure de construire une HList informes récursive

object HList1Test extends App { 
    import shapeless.{HList, HNil} 
    import shapeless.syntax._ 
    import shapeless.ops._ 
    def myFunc(list: List[Int], result: HList = HNil) : HList = { 
     def double (i: Int) : HList = if (i % 2 == 0) 2 * i :: HNil else { (2 * i).toString :: HNil} 
     list match { 
     case h :: t => { 
      myFunc(t, double(h) ::: result) 
     } 
     case Nil => result 
     } 
    } 
    println(myFunc(List(1, 2, 3))) 
} 

Mais j'obtiens l'erreur

Error:(16, 33) could not find implicit value for parameter prepend: shapeless.ops.hlist.Prepend[shapeless.HList,shapeless.HList] 
      myFunc(t, double(h) ::: hlist) 
Error:(16, 33) not enough arguments for method :::: (implicit prepend: shapeless.ops.hlist.Prepend[shapeless.HList,shapeless.HList])prepend.Out. 
Unspecified value parameter prepend. 
      myFunc(t, double(h) ::: hlist) 

Mon objectif final était d'avoir un HList avec "2" :: 4 :: "6" :: HNil

Répondre

3

Dire que 2 * i :: HNil et (2 * i).toString :: HNil ont le même type que HList (plutôt que Int :: HNil et String :: HNil en conséquence) est o rugueux.

Depuis double retourne en fait des valeurs de types Int :: HNil ou String :: HNil en fonction de la valeur de son argument d'entrée, double est un Poly. Il en est ainsi de myFunc.

object double extends Poly1 { 
    implicit def evenCase[N <: Nat](implicit 
     mod: Mod.Aux[N, _2, _0], 
     toInt: ToInt[N]): Case.Aux[N, Int :: HNil] = 
     at(n => 2 * toInt() :: HNil) 

    implicit def oddCase[N <: Nat](implicit 
     mod: Mod.Aux[N, _2, _1], 
     toInt: ToInt[N]): Case.Aux[N, String :: HNil] = 
     at(n => (2 * toInt()).toString :: HNil) 
    } 

    object myFunc extends Poly2 { 
    implicit def hNilCase[R <: HList]: Case.Aux[HNil, R, R] = at((_, r) => r) 

    implicit def hConsCase[H <: Nat, T <: HList, 
          dblH <: HList, R <: HList, 
          P <: HList, Out <: HList](implicit 
     dbl: double.Case.Aux[H, dblH], 
     prepend: Prepend.Aux[dblH, R, P], 
     myF: myFunc.Case.Aux[T, P, Out]): Case.Aux[H :: T, R, Out] = 
     at { case (h :: t, r) => myFunc(t, double(h) ::: r) } 
    } 

    println(myFunc(_1 :: _2 :: _3 :: HNil, HNil)) //"6" :: 4 :: "2" :: HNil 
+1

Réponse incroyable Dmytro! –