2017-11-20 16 views
0

私はユーザーの入力に依存する型クラスを作成しようとしています。Scalaの抽象型、変数、および型式

sealed trait H 
case object Ha extends H 
case object Hb extends H 

と型クラス:我々はいくつかのケースオブジェクトを持っている想像し、私たちは持っていることを覚えて

variableComingFromMainArgs match { 
    case "a" => Foo.bar[Ha.type] _ 
    case "b" => Foo.bar[Hb.type] _ 
} 

:私は試合を使用して実用的なソリューションを見つけながら

trait Foo[A] { 
    def bar: String 
} 

object Foo { 
    def bar[A : Foo] = implicitly[Foo[A]].bar 

    implicit object FooA extends Foo[Ha.type] { 
     override def bar: String = "A" 
    } 

    implicit object FooB extends Foo[Hb.type] { 
     override def bar: String = "B" 
    } 
} 

Scalaの抽象型であるため、私のケースクラスを次のように変更することができます:

プログラムへのユーザーの入力に応じたとき

さて、私はこれがない何らかの理由で、しかし ヴァル変数のようなもの=ハ のprintln(Foo.bar [variable.T])

を行うことができます仕事とエラーが私のために非常に有用ではありません。

error: could not find implicit value for evidence parameter of type Foo[variable.T] 
     println(Foo.bar[variable.T]) 

任意のアイデアこれは、いない場合は克服できるのであれば、なぜですか?

ありがとうございました。

答えて

1

インプリシットはコンパイル時の構造体であるため、原則的にユーザー入力に直接依存することはできません(プログラマは、たとえば、パターンマッチングを使用してプログラマに渡すことができます)。

次のコードを検討してください。

trait H { 
    type A 
} 

case object Ha extends H { 
    override type A = Int 
} 

case object Hb extends H { 
    override type A = Long 
} 

trait Adder[T] { 
    def add(a: T, b: T): T 
} 

implicit object IntAdder extends Adder[Int] { 
    override def add(a: Int, b: Int): Int = a + b 
} 

implicit object LongAdder extends Adder[Long] { 
    override def add(a: Long, b: Long): Long = a + b 
} 

def addWithAdder(input: H)(a: input.A, b: input.A)(implicit ev: Adder[input.A]): input.A = ev.add(a, b) 

val x: Int = addWithAdder(Ha)(3, 4) 
val y: Long = addWithAdder(Hb)(3, 4) 

addWithAdderメソッドに注目しましょう。パス依存型のおかげでコンパイラはこのタスクに対して正しい暗黙的に選択することができます。しかし、まだこの方法は、基本的には次のと同じです:

def add[T](a: T, b: T)(implicit ev: Adder[T]) = ev.add(a, b) 

1を持つことができる最初の唯一の利点は、あなたがすべてのインスタンスを自分で提供してHが密閉されたときに(自分のタイプを追加するために、あなたのコードのユーザーを停止することができるということですすべての実装は最終的です)。

+0

ええと、十分に..私が言及したようにパターンマッチングを使用することを除いて、これには何の問題もないと思います。ありがとう! – Crembo

関連する問題