2015-09-08 51 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

你会得到哪个错误? –