2

Function1 または PartialFunction で widen 関数を定義したいと思います。

次のようなユースケースがあるため、これを行いたいと思います。

class A
class B extends A

def foo(fun: Function[B, A]) = {
    bar(fun.widen[A])
}

def bar(pf: PartialFunction[A, A]) = ???

上記のように、これを達成するために、次のような widen 関数を定義することを考えました。

implicit class AugmentedFunction[T, U](fun: T => U) {
    def widen[T1 >: T]: PartialFunction[T1, U] = { case t: T => fun(t) }
}

残念ながら、これは消去のために機能しません。TypeTags の使用を検討してみましたが、これをコンパイラが満足する方法で表現できなかったようです。

明確化: 動作しないと言うときは、ScalaKata のコード スニペットの特定のケースで、実際には例外をスローして「定義されていません」と出力すべきではないのに、使用すると例外がスローされることを意味します (ScalaKata コード スニペットを参照)。

私の質問:

この問題を正しく解決するにはどうすればよいですか? Scalaz や Shapeless には、私が気付いていない機能が既に存在するのでしょうか? そもそもこんなことして意味あるの?

すべてのコードを含むスニペットを次に示します: http://www.scalakata.com/527bb729e4b0b1a1c4db1a73

4

3 に答える 3

3

クラスマニフェストでこれを行うことができると思います:

implicit class AugmentedFunction[T, U](fun: T => U)(implicit m: Manifest[T]) {
  def widen[T1](implicit m1: Manifest[T1]): PartialFunction[T1, U] = {
    case a if(m <:< m1) => fun(a.asInstanceOf[T]) 
  }
}

class A
class B extends A
class C

val theFun: B => A = (b: B) => b

theFun.widen[A].isDefinedAt(new B) // true
theFun.widen[C].isDefinedAt(new C) // false
于 2013-11-07T15:41:34.370 に答える
0

まあ、エラーはそれをすべて言います: java.lang.ClassCastException: ScalaKata$A$1 cannot be cast to ScalaKata$B$1. 基本的にfoo( (a: B) => new A, new A)、値を呼び出すと、実際にタイプをパラメーターとしてA受け入れるラムダに渡されるため、ジェネリックからスペシフィックにキャストすることはできません。BAB

次のようなものを使用する必要があります。

foo( (a: Ai) => new Ai, new Ai)
foo( (a: Ci) => new Ai, new Ci)
foo( (a: Ai) => new Ai, new Bi)

基本的に、2 番目のパラメーターはラムダ引数型のサブタイプにする必要があります。

于 2013-11-07T05:45:59.177 に答える