1

その問題については多くの質問がありましたが、残念ながら私の問題を解決するものはないようです。

私は一般的なscalaクラスを書きました、それを呼びましょう

class MyClass[A]() { ... }

それに応じたオブジェクトと同様に:

object MyClass() { ... }

MyClass内で、動作が指定されたタイプAに依存する関数を定義したいと思います。たとえば、タイプ(A、A)=>ブール値の「小さい」関数を定義したいとします。デフォルトでは「true」が返されます。要素が何であっても、Int、Floatなどの特定のタイプに対して正しい結果を返すことを目的としています。

私の考えは、次のように「小さい」をクラスのメンバーとして定義することでした。

class MyClass[A]() {

    val someArray = new Array[A](1) // will be referred to later on

    var smaller:(A,A) => Boolean = MyClass.getSmallerFunction(this)

    ...some Stuff...

}

object MyClass {

    def getSmallerFunction[A](m:MyClass[A]):(A,A) => Boolean = { 

        var func = (a:Boolean, b:Boolean) => true

        // This doesn't compile, since the compiler doesn't know what 'A' is
        if(A == Int) func = ((a:Int, b:Int) => (a<b)).asInstanceOf[(A,A) => Boolean)]

        // This compiles, but always returns true (due to type erasure I guess?)
        if(m.isInstanceOf[MyClass[Float]]) func = ((a:Float, b:Float) => (a<b)).asInstanceOf[(A,A) => Boolean)]

        // This compiles but always returns true as well due to the newly created array only containing null-elements
        if(m.someArray(0).isInstanceOf[Long]) func = ((a:Long, b:Long) => (a<b)).asInstanceOf[(A,A) => Boolean)]

    }

    ...some more stuff...

}

getSmallerFunctionメソッドには、私が実験した実装のいくつかが含まれていますが、どれも機能しません。

しばらくトピックを調査した後、最初はマニフェストが進むべき道のように見えましたが、残念ながら、オブジェクトMyClassにはクラスのコンストラクター呼び出しも含まれているため、ここでは機能しないようです。コードを変更する方法-マニフェストを使用するために必要な情報が不足していることにコンパイラーが常に腹を立てる結果になります。マニフェストベースのソリューションがあるかもしれませんが、私は確かにまだそれを見つけていません。

注:「小さい」関数の使用法は単なる例であり、実装したいこの種の関数がいくつかあります。この特定のケースでは、比較可能なタイプAのみを許可できることはわかっていますが、それは実際には私が達成しようとしていることではありません。

テキストの壁でごめんなさい-私の問題を理解することが可能であることを願っています。

よろしくお願いします。

編集:

たぶん、もう少し詳しく説明する必要があります。私がやろうとしていたのは、画像プログラミング用のライブラリの実装でした(主に個人的な使用のため)。'MyClass'は、実際にはクラス'Pixelmap'であり、タイプAの「ピクセル」の配列と、ピクセル操作の特定のメソッドが含まれています。これらのPixelmapはどのタイプでもかまいませんが、私は主にFloatおよびColorデータ型を使用し、マスクにはブール値を使用することもあります。私が必要とするデータ型依存関数の1つは'blend'です(ただし、'smaller'も使用されます)。これは、タイプAの2つの値の間を補間し、たとえば、そのようなPixelmapのスムーズなサイズ変更に使用できます。デフォルトでは、このブレンド関数(タイプ(A、A、Float)=> A)は最初に指定された値を返すだけですが、タイプFloat、Colorなどのピクセルマップの場合、適切な補間が定義されることを意味します。

編集2:

少なくとも私の特定のケースでは、問題を解決するための適切な方法を見つけたようです。ただし、これは実際には回避策です。

タイプAの暗黙的なパラメーターをMyClassに追加しただけです。

class MyClass[A]()(implicit dummy:A) { ... }

たとえば、インスタンスm:MyClassのタイプAが「Float」であるかどうかを確認したい場合は、「m.dummy.isInstanceOf[Float]」を使用できます。これを実際に機能させるために、必要なすべてのデータ型に対して事前定義された暗黙の値の束をMyClassオブジェクトに追加しました。

object MyClass {

    implicit val floatDummy:Float = 0.0f
    implicit val intDummy:Int = 0
    ...

}

これは実際には適切な解決策のようには感じられませんが、問題をかなりうまく回避できるようです。

4

1 に答える 1

2

正直なところ、あなたが何をしようとしているのかまだ完全にはわからないので、たくさんのことを省略しました. しかし、ここにあなたを助けるかもしれない解決策があります.

trait MyClass[A] {
  def smaller: (A,A) => Boolean
}

object MyClass {
  implicit object intMyClass extends MyClass[Int] {
    def smaller = (a:Int, b:Int) => (a < b)
  }
  implicit object floatMyClass extends MyClass[Float] {
    def smaller = (a:Float, b:Float) => (a < b)
  }
  implicit object longMyClass extends MyClass[Long] {
    def smaller = (a:Long, b:Long) => (a < b)
  }

  def getSmallerFunction[T : MyClass](a: T, b: T) = implicitly[MyClass[T]].smaller(a, b)
}

MyClassアイデアは、メソッドを使用して、オブジェクトの下に暗黙的なオブジェクトとして小さなメソッドを定義することですgetSmallerFunction。このメソッドは、型の境界を満たす型クラスのインスタンスを探すという意味で特別です。次に行くことができます:

println(MyClass.getSmallerFunction(1, 2))

そして、使用する正しい方法を自動的に認識します。この手法を拡張して、配列の例を処理できます。これは、型クラスとは何かについての優れたチュートリアル/プレゼンテーションです。

編集:実際の関数が返されることを望んでいることに気づきました。私の場合、あなたのように型パラメーターが失われます。しかし、結局のところ、型に応じてメソッドを選択的に呼び出せるようにしたいだけなら、ここで詳しく説明したアプローチが役に立ちます。

于 2012-11-28T15:13:54.453 に答える