2017-11-21 5 views
0

私は連鎖した暗黙関数のシステムに取り組んでいます。これは以下の簡単な例に似ています。テストc1.payload == c2.payloadは、 "タイプスペース"にないテストを表しています。私はwitnessEvidenceの定義のためにマクロに入ることを期待していましたが、Scalaは明示的に任意の型の暗黙的な引数を持つマクロ定義を許可していません(WeakTypeTag値のみ!)ので、これをどのように進めるかについて少し不便です。以下のコードは論理的に私が何をしたいのかを示していますが、暗黙の関数は条件付きで証拠を生成したり生成したりすることはできません(マクロ実装内にない限り)。条件付きでスカラにimplicitsを生成する

case class Capsule[T](payload: Int) 

trait A 
trait B 
trait C 

implicit val capa = Capsule[A](3) 
implicit val capb = Capsule[B](3) 
implicit val capc = Capsule[C](7) 

case class Evidence[T1, T2](e: Int) 

implicit def witnessEvidence[T1, T2](implicit c1: Capsule[T1], c2: Capsule[T2]): Evidence[T1, T2] = { 
    if (c1.payload == c2.payload) 
    Evidence[T1, T2](c1.payload) 
    else 
    // Do not produce the evidence 
} 

def foo[T1, T2](implicit ev: Evidence[T1, T2]) = ev.e 

val f1 = foo[A, B] // this should compile 
val f2 = foo[A, C] // this should fail with missing implicit! 
+0

は 'Capsule'値、特にその' payload'ですあなたはシングルトン型を使用できることを行うために、コンパイル時に知られているフィールド? –

+1

'payload'値は、暗黙的な連鎖の副産物として生成されます(この部分は正常に動作しているようです)。したがってコンパイル時に利用可能です。しかし、情報は型の形でコード化されていません。私は、情報がHListレコードとしてエンコードされ、暗黙的な解決がその代わりに手に入る代わりの方法に取り組んでいます。 – eje

答えて

4

暗黙的な解決はコンパイル時に行われ、バリュー等価性のテストは実行時に行われるため、これはそのままでは不可能です。

コンパイラに値を型として理解させる必要があるので、2つの3つの型が等しいかどうかを調べ、それを使ってcapa =:= capbを推論することができます。 https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#singleton-typed-literals

あなたはプレーンな等価比較を超えて算術演算を行う必要がある場合、あなたはNatを使用する必要があります:https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/nat.scala

+0

はい、私が比較したい実際の構造はもっと複雑で、これは別の解決法に関する私の他の関連する問題を引き起こしました:https://stackoverflow.com/questions/47421083/test-two-scala-shapeless-hlist-等価性のための型 - 暗黙的に - – eje