2016-05-20 18 views
2

私は現在Shapelessで実験を始めました。私の最初の試みは次のコード例でした。型崩れのバージョンは2.3.0で、Scalaのバージョン2.11.7:私はLabelledGenericsためlgen暗黙のパラメータの値を提供しなかったので、シェイプレスで一般的な型変換

import org.scalatest._ 
import shapeless._ 

sealed trait Dog { 
    def favoriteFood: String 
} 

sealed trait Cat{ 
    def isCute: Boolean 
} 

sealed trait Green 

sealed trait Blue[G <: Green]{ 
    def makeGreen(): G = { 
    val blueGen = LabelledGeneric[this.type] 
    val greenGen = LabelledGeneric[G] 
    val blue = blueGen.to(this) 
    val green = greenGen.from(blue) 
    green 
    } 
} 

case class BlueDog(override val favoriteFood: String) extends Dog with Blue[GreenDog] 
case class GreenDog(override val favoriteFood: String) extends Dog with Green 

case class GreenCat(override val isCute: Boolean) extends Cat with Green 
case class BlueCat(override val isCute: Boolean) extends Cat with Blue[GreenCat] 

class ShapelessExperimentsTest extends FlatSpec with Matchers { 

    "Make green" should "work" in { 
    val blueDog = new BlueDog("Bones") 
    val greenDog: GreenDog = blueDog.makeGreen 
    assert(greenDog.favoriteFood == "Bones") 

    val blueCat = new BlueCat(true) 
    val greenCat: GreenCat = blueCat.makeGreen 
    assert(greenCat.isCute) 
    } 
} 

は、このコードはいえコンパイルされません。コンパイルエラーは、したがって、私の問題は、私は例を動作させるために、これらの暗黙を提供するための正しい方法を見つけることができなかったということです

...ShapelessExperimentsTest.scala:16: could not find implicit value for parameter lgen: shapeless.LabelledGeneric[Blue.this.type] 

...ShapelessExperimentsTest.scala:17: could not find implicit value for parameter lgen: shapeless.LabelledGeneric[G] 

です。誰もこれで私を助けることができますか?関数の本体で

val blueGen = LabelledGeneric[this.type] 
    val greenGen = LabelledGeneric[G] 

コンパイルされません:

+1

LabelledGenericは抽象型やシングルトン型で動作するように設計されているとは思われません。 – pedrofurla

答えて

2

悲しいことに、Scalaで、すべての「ジェネリック -nessのビットが」呼び出しサイトに固定する必要があり、これは基本的に何かのようにすることを意味しますなぜならコンパイラは "this.type"と "G"を釘付けにすることができないからです。再び

def makeGreen[T](implicit blueGen: LabelledGeneric.Aux[this.type, T], greenGen: LabelledGeneric.Aux[G, T]): 

(AUXセンドタイプの計算をするだけのパターンであるあなたがそれに慣れていない場合、私は非常にthis記事を示唆)

:幸いにも、暗黙のは、まさにこの問題を解決するための言語でありますしかし、コンパイラはthis.typeが実際にcaseクラスであり、暗黙のLabelledGenericインスタンスを見つけることができないため、このコードはおそらくコンパイルされません。

代わりに、あなたはこのような何かにあなたのコードをリファクタリングすることができます:ここで

import org.scalatest._ 
import shapeless._ 

sealed trait Animal 

sealed trait Dog extends Animal { 
    def favoriteFood: String 
} 

sealed trait Cat extends Animal { 
    def isCute: Boolean 
} 

sealed trait Color 
sealed trait Green extends Color 
sealed trait Blue extends Color 

trait GreenColorable[A <: Animal, G <: Green] { 
    def makeGreen[T](animal: A)(implicit animalGen: LabelledGeneric.Aux[A, T], greenGen: LabelledGeneric.Aux[G, T]): G = { 
    val blue = animalGen.to(animal) 
    val green = greenGen.from(blue) 

    green 
    } 
} 

object Colorables { 
    def GreenColorable[A <: Animal, G <: Green] = new GreenColorable[A, G] {} 
} 

case class BlueDog(override val favoriteFood: String) extends Dog with Blue 
case class GreenDog(override val favoriteFood: String) extends Dog with Green 

case class GreenCat(override val isCute: Boolean) extends Cat with Green 
case class BlueCat(override val isCute: Boolean) extends Cat with Blue 

class ShapelessExperimentsTest extends FlatSpec with Matchers { 

    "Make green" should "work" in { 
    val blueDog = new BlueDog("Bones") 
    val greenDogColorable= Colorables.GreenColorable[BlueDog, GreenDog] 
    val greenDog = greenDogColorable.makeGreen(blueDog) 
    assert(greenDog.favoriteFood == "Bones") 

    val blueCat = new BlueCat(true) 
    val greenCatColorable = Colorables.GreenColorable[BlueCat, GreenCat] 
    val greenCat: GreenCat = greenCatColorable.makeGreen(blueCat) 
    assert(greenCat.isCute) 
    } 
} 

、実際の変換は、パラメータとして、実際のケースクラスの入力および出力の種類を取る別の型クラスに移動されます。

関連する問題