2014-06-10 94 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