2015-08-27 4 views
8

साथ निराकार टैग का उपयोग करना मान लीजिए मैं के रूप में वर्णित hereLabelledGenerics

मामले वर्ग सामान्य प्रतिनिधित्व पार करने के लिए करना चाहते हैं मैं क्षेत्रों का वर्णन करने के कुछ typeclass परिभाषित किया है:

:

trait Described[X] extends (X => String) 
object Described{ 
    def apply[X](x: X)(implicit desc: Described[X]) = desc(x) 
} 

कुछ उदाहरण परिभाषित किया जाता है

implicit object DoubleDescribed extends Described[Double]{ 
    def apply(x: Double) = x.formatted("%01.3f") 
} 

और सामान्य उपयोगकर्ता:

import shapeless._ 
import shapeless.labelled.FieldType 
import shapeless.ops.hlist.LeftFolder 

object DescrFolder extends Poly2{ 
    implicit def field[X, S <: Symbol](implicit desc: Described[X], 
               witness: Witness.Aux[S]): 
    Case.Aux[Seq[String], FieldType[S, X], Seq[String]] = 
    at[Seq[String], FieldType[S, X]](
    (descrs, value) => descrs :+ f"${witness.value.name}: ${desc(value)}") 
} 

def describe[T <: Product, Repr <: HList](struct: T) 
     (implicit lgen: LabelledGeneric.Aux[T,Repr], 
       folder: LeftFolder.Aux[Repr, Seq[String], DescrFolder.type, Seq[String]] 
          ): String = { 
    val repr = lgen.to(struct) 
    val descrs = folder(repr,Vector()) 
    descrs.mkString(struct.productPrefix + "{", ",", "}") 
} 

तो अब मैं

case class Point(x: Double, y: Double, z: Double) 
describe(Point(1,2,3.0)) 

लिख सकते हैं और अब

res1: String = Point{x: 1,000,y: 2,000,z: 3,000}

मिल सकता है मैं shapeless टैग का उपयोग कुछ क्षेत्र मेटाडाटा को परिभाषित करना चाहते हैं: सफलतापूर्वक अब

import tag._ 
trait Invisible 
val invisible = tag[Invisible] 
implicit def invisibleDescribed[X](implicit desc: Described[X]) 
      : Described[X @@ Invisible] = 
    new Described[X @@ Invisible]{ 
    def apply(x: X @@ Invisible) = desc(x: X) + "[invisible]" 
    } 

तो Described(invisible(0.5))

उत्पन्न करता है 10

res2: String = 0,500[invisible]

लेकिन नए सिरे से परिभाषित

case class Point(x: Double, y: Double, z: Double @@ Invisible) 

describe(Point(1,2,invisible(3.0))) 

साथ संकलन त्रुटि पैदावार:

Error: diverging implicit expansion for type LeftFolder.Aux[this.Out,Seq[String],DescrFolder.type,Seq[String]] starting with method invisibleDescribed in class ...

मैं उस प्रकार X with Tag[Y] with KeyTag[K,X]FieldType[S, X] के रूप में पहचान नहीं है अनुमान लेकिन लगता है कि नहीं कर सकता है कि यह कैसे तय करने के लिए।

ऐसी स्थिति के लिए कोई उचित LeftFolder कैसे परिभाषित कर सकता है?

उत्तर

0

आपकी समस्या में shapeless शामिल नहीं है। यह वास्तव में सरल किया जा सकता है:

trait Described[T] 
trait Invisible 

implicit val doubleDescribed: Described[Double] = ??? 

implicit def invisibleDescribed[T](
    implicit desc: Described[T] 
): Described[T with Invisible] = ??? 

implicitly[Described[Double with Invisible]] 

Double @@ Invisible कर सकते हैं Double with Invisible के रूप में "का प्रतिनिधित्व" किया। ध्यान दें कि Double with Invisible <: Double

जब संकलक एक अंतर्निहित Described[Double with Invisible] प्राप्त करने का प्रयास करता है तो यह सही विस्तार को अलग करने के बारे में सही मायने रखता है: doubleDescribed और invisibleDescribed

implicit def invisibleDescribed[X, I <: X @@ Invisible](
    implicit desc: Described[X] 
): Described[I] = new Described[I]{ 
    def apply(x: I) = desc(x: X) + "[invisible]" 
} 
:

अपने मूल कोड के लिए वापस जा रहे हैं, एक आसान ठीक बस के पुनर्लेखन के लिए invisibleDescribed के रूप में हो सकता है