2014-06-10 44 views
3

我在这里经历了一些关于同一事物的问题,但似乎无法为我的案例找到解决方案。再次在HLists上映射

在本质上我需要定义接受一个x,的方法,其中x <:T和一个L,其中L <:HList并且使用从T.

继承每个可能的类中定义的过度POLY1映射升

我已经尝试了几种方法,我的最后一次尝试导致了一些非常可怕的scalac炸弹。我一定在做一些非常愚蠢的事情,但似乎无法摆脱它的困扰!

import shapeless._ 
import ops.hlist._ 

trait T { 
    val fun: Poly1 
} 
case class C() extends T { 
    object fun extends Poly1 { 
    implicit val caseInt = at[Int](i => "int " + i) 
    override def toString = "here I am, poly1" 
    } 
} 
def method[X <: T](x: X) = x.fun 
method(C()) 
res0: shapeless.Poly1 = here I am, poly1 

def method2[X <: T, L <: HList](x: X, l: L)(implicit m: Mapper[x.fun.type, L]) = l map x.fun 
method(C(), 23 :: HNil) //BOOM! 
+0

正如我在Twitter上刚才提到的,你[可能的运气(HTTP ://stackoverflow.com/questions/11442440/unable-to-map-on-hlist/11442871#comment15099885_11442871)。 –

+0

@TravisBrown说了什么......''C()'是易变的,它会挫败隐式搜索'fun'的情况。 –

回答

1

我不知道这是正是你想要什么,但它的工作原理:

object test { 

import shapeless._ 
import ops.hlist._ 

    trait T { 

    type PT <: Singleton with Poly1 
    val fun: PT 
    } 

    object C extends T { 

    type PT = funImpl.type 
    object funImpl extends Poly1 { 
     implicit val caseInt = at[Int](i => "int " + i) 
     override def toString = "here I am, poly1" 
    } 
    val fun = funImpl 
    } 

    case class D() extends T { 

    type PT = funImpl.type 
    object funImpl extends Poly1 { 
     implicit val caseInt = at[Int](i => "int " + i) 
     override def toString = "here I am, poly1" 
    } 
    val fun = funImpl 
    } 


    def method[X <: T](x: X) = x.fun 
    val ok = method(C) 

    // singletonize it 
    implicit def toOps[X <: T](x: X): Method2Ops[x.type] = { Method2Ops(x: x.type) } 
    case class Method2Ops[X <: Singleton with T](val x: X) { 

    def method2[L <: HList](l: L)(implicit m: Mapper[X#PT, L]) = l map (x.fun: X#PT) 
    } 

    val okC = C method2 (23 :: HNil) 

    val d = D() 

    val okD = d method2 (23 :: HNil) 
} 
+0

我可以说,诀窍的本质是,在隐式转换中,您传递'x:x.type',并在'Method2Ops'中需要单例? 这里还有什么重要的? – laughedelic