2016-07-26 6 views
1

Hlistを折り畳んでリストを折りたたむときにHListをfoldLeftにすることはできません。シェイプレス:foldLeft on hlistコンパイルエラー

object wrapInList extends Poly1 { 
    implicit def intCase = at[Int]{v => List(v)} 
    implicit def stringCase = at[String]{v => List(v)} 
} 

object mergeToString extends Poly1 { 
    implicit def intCase = at[Int](_.toString()) 
    implicit def stringCase = at[String](identity) 
} 

object foldListPoly extends Poly2 { 
    implicit def foldToList[T](implicit st: wrapInList.Case.Aux[T, List[T]]) = 
    at[List[T], T]{ (acc, t) => acc ::: wrapInList(t) } 
    implicit def foldToString[T](implicit st: mergeToString.Case.Aux[T, String]) = 
    at[String, T]{ (acc, t) => acc + mergeToString(t)} 
} 

val hList = "aoeu" :: 42 :: HNil 
val foldedHlist = hList.foldLeft("")(foldListPoly) 
val foldedHList2 = hList.foldLeft(Nil)(foldListPoly) 

Erorr問題は、あなたがhList(42の次の要素と互換性がありませんwrapInListで "aoeu" のList[String]を生成することこれはfoldedHList2

could not find implicit value for parameter folder: 
shapeless.ops.hlist.LeftFolder[shapeless.::[String,shapeless.::[Int,shapeless.HNil]],scala.collection.immutable.Nil.type,com.test.Test.foldListPoly.type] 
+1

エラーを追加できますか? –

+0

私はコンパイルエラーの質問を更新しました。 – andresrcom

答えて

2

ご注意:また

object wrapInList extends Poly1 { 
    implicit def intCase = at[Int]{v => List[Any](v)} 
    implicit def stringCase = at[String]{v => List[Any](v)} 
} 

object foldListPoly extends Poly2 { 
    implicit def foldToList[T](implicit st: wrapInList.Case.Aux[T, List[Any]]) = 
    at[List[Any], T]{ (acc, t) => acc ::: wrapInList(t) } 
} 

、明示的List[Any]としてNilを入力する必要がその形状のないものはHListruntimeListメソッドを定義しており、HListからList[Any]を効率的に計算し、さらにをより正確に型付けされたに変換するtoListメソッドを定義しています。それにもかかわらず、この操作がfoldを使ってどのように実行できるかを見るのは興味深い。

ここにはいくつかのシワがあります。最初に検討するのは、ここに蓄積しているListのタイプでなければなりません。おそらく、結果として得られるリストの要素タイプが、あなたが折りたたんでいるHListの要素の型の最小の上限(LUB)であることを望むでしょう。そのタイプの結果を得るには、私たちが行ったようにLUBを計算する必要があります。

また、初期値としてNilを収容する必要があります。 Nilは、タイプList[Nothing]の値であり、これは暗黙のインデックスをList[T]で解決する必要がある場合には問題となります。変数TNilの型に一致するようにNothingにインスタンス化する必要がありますが、残念なことにScalaの型推論器では型変数の値として型Nothingが「未解決」と扱われます...結果は暗黙の解決です偽りに失敗するでしょう。この問題を回避するには、Nil.typeに対して明示的にケースfoldListPolyを指定する必要があります。一緒にこれを置く

我々は、それぞれの場合に得られたリストの要素タイプはHListの要素タイプのLUBあること

object wrapInList extends Poly1 { 
    implicit def default[T] = at[T]{v => List(v)} 
} 

object foldListPoly extends Poly2 { 
    implicit def foldToListNil[U](implicit st: wrapInList.Case.Aux[U, List[U]]) = 
    at[Nil.type, U]{ (acc, u) => wrapInList(u) } 

    implicit def foldToList[T, U, L, LL](
    implicit st: wrapInList.Case.Aux[U, List[U]], 
    lub: Lub[T, U, L], 
    llub: Lub[List[T], List[U], LL], 
    ev: LL =:= List[L] 
) = at[List[T], U]{ (acc, u) => llub.left(acc) ::: llub.right(wrapInList(u)) } 
} 

scala> ("aoeu" :: 42 :: HNil).foldLeft(Nil)(foldListPoly) 
res0: List[Any] = List(aoeu, 42) 

scala> (13 :: 23 :: HNil).foldLeft(Nil)(foldListPoly) 
res1: List[Int] = List(13, 23) 

scala> (23 :: true :: HNil).foldLeft(Nil)(foldListPoly) 
res2: List[AnyVal] = List(23, true) 

は注意、で終わります。

0

のコンパイルにInt)。あなたは(最小の上限ではなく)List[Any]と一緒に暮らすことができる場合、あなたはこのようにそれを行うことができます。

val foldedHList2 = hList.foldLeft(Nil:List[Any])(foldListPoly) 
+0

私は互換性のない型の考えを持っていましたが、残念ながらこのコードはコンパイルされず、 'hList'を折りたたんだときに同じエラーが発生します。 – andresrcom

+0

申し訳ありません、 'List [Any]'型を含むメソッド呼び出しを含めるのを忘れていました。 – devkat