2015-09-08 85 views
5

下面的代碼裏面似乎很明顯,編譯和運行映射在HList功能

case class Pair(a: String, b: Int) 

val pairGen = Generic[Pair] 

object size extends Poly1 { 
    implicit def caseInt = at[Int](x => 1) 
    implicit def caseString = at[String](_.length) 
} 

def funrun(p: Pair) = { 
    val hp: HList = pairGen.to(p) 
    hp.map(size) 
} 

但是編譯器說「無法找到參數映射器內含價值」。在我的使用案例中,我想通過一個HList進行映射以獲取字符串的HList,然後將字符串的HList轉換爲Scala List [String]。有任何想法嗎?

回答

8

首先,我們可以創建一個Poly1類似size,我們可以使用一個HList映射到Strings一個HList

object strings extends Poly1 { 
    implicit def caseInt = at[Int](_.toString) 
    implicit def caseString = at[String](identity) 
} 

你已經在使用Generic[Pair]把一個PairHList,但你不能在你的hp映射,因爲在你的funrun沒有證據,你可以映射在它。我們可以通過使用隱式參數來解決這個問題。

def funRun[L <: HList, M <: HList](
    p: Pair 
)(implicit 
    gen: Generic.Aux[Pair, L], 
    mapper: Mapper.Aux[strings.type, L, M] 
) = gen.to(p).map(strings) 
  • 我們的第一個隱式參數gen可以把PairHList L類型。
  • 我們的第二個隱含參數mapper可以使用我們的strings多態函數L類型的HList映射到M類型的HList

我們現在可以使用funRun把一個PairStringsHList

scala> funRun(Pair("abc", 12)) 
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil 

但是你想返回List[String]。爲了把我們的HListM(映射到String的結果)的List[String]我們需要一個ToTraversable,所以我們增加第三隱含參數:

import shapeless._, ops.hlist._ 

def pairToStrings[L <: HList, M <: HList](
    p: Pair 
)(implicit 
    gen: Generic.Aux[Pair, L], 
    mapper: Mapper.Aux[strings.type, L, M], 
    trav: ToTraversable.Aux[M,List,String] 
): List[String] = gen.to(p).map(strings).toList 

,我們可以爲使用:

scala> pairToStrings(Pair("abc", 12)) 
res2: List[String] = List(abc, 12) 
+0

謝謝@Peter!這正是我所期待的! – arapmv

+0

我關閉這個線程我在圈子裏試圖理解去了之後爲什麼以下基本增強複合型不起作用:'A級[T](VAL X:T); 對象克延伸POLY1 { 隱DEF caseString =在[字符串] {身份} }; DEF toStr [L <:HList]( 一個:A [字符串] )(隱式 創:Generic.Aux [A [字符串],L], 映射器:映射器[g.type,L] ) = gen.to(a).map(g)' – arapmv

+0

你會得到哪個錯誤? –