2016-07-26 67 views
1

當摺疊到列表時,無法獲得foldLeft處理HList,當我將Hlist摺疊到字符串時,一切正常。Shapeless: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上編譯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

請注意該無定形定義了HList上的runtimeList方法,該方法有效計算來自HListList[Any]以及將HList轉換爲更精確類型的的toList方法。儘管如此,有趣的是看到如何使用fold執行此操作。

這裏有幾處皺紋。首先要考慮的是你在這裏積累的List的類型應該是什麼。很可能你會希望結果列表的元素類型是你摺疊的HList元素類型的最小上限(LUB)。爲了得到這種類型的結果,我們需要計算LUB。

我們還需要容納Nil作爲初始值。 NilList[Nothing]類型的值,在需要解析由List[T]索引的隱式的情況下,這是有問題的。類型變量T必須在Nothing處實例化以匹配Nil的類型,但不幸的是,Scala的類型推理器將類型Nothing視爲類型變量的值,意思是「未解決」的意思......其結果是隱式解析會虛假地失敗。要解決此問題,我們必須爲Nil.type提供foldListPoly的明確情況。

把此我們一起結束了,

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) 

注意,在每種情況下所得到的列表的元素類型是元素類型的HList的LUB。

0

的問題是,你在wrapInList生成 「aoeu」 一List[String]這是不符合的hList(下一個元素42,其兼容是Int)。如果你能List[Any](而不是最少的上限)生活,你可以做這樣的:

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) } 
} 

此外,你必須明確地鍵入NilList[Any]

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

我得到了不兼容類型的想法,但不幸的是,這個代碼不能編譯,並且在試圖摺疊'hList'時給出相同的錯誤。 – andresrcom

+0

對不起,我忘了包含包含'List [Any]'類型的方法調用。 – devkat