20

関数リテラルでジェネリック型パラメーターを許可する構文はありますか? 次のような方法でラップできることはわかっています。

def createLongStringFunction[T](): (T) => Boolean = {
  (obj: T) => obj.toString.length > 7
}

しかし、すべての型 T に対してメソッドを呼び出し、新しい関数を取得する必要があります。言語リファレンスを調べたところ、関数リテラル構文がコンパイラによって、それ自体が汎用入力型を持つFunctionnオブジェクトのインスタンスに変換されていることがわかりますが、コンパイラの魔法が作成時にこれらのパラメーターを認識しているように見えます。実際に「 Functionnの 1 つ以上の型パラメーターをバインドしないままにする」ことができる構文は見つかりませんでした。私が好むのは、次のようなものです。

// doesn't compile
val longStringFunction: [T](T) => Boolean = (obj: T) => obj.toString.length > 7

そのようなものは存在しますか?さらに言えば、展開されるメソッドにジェネリック パラメーターがある場合の eta 展開関数の明示的な型は何ですか?

これは純粋に不自然で役に立たない例です。もちろん、ここで Any を使用する関数を作成することもできます。

4

4 に答える 4

21

いいえ、型パラメーターはメソッドにのみ適用され、関数オブジェクトには適用されません。例えば、

def f[T](x: T) = x     //> f: [T](x: T)T
val g = f _            //> g: Nothing => Nothing = <function1>
// g(2)                // error
val h: Int=>Int = f _  //> h  : Int => Int = <function2>
h(2)                   //> res0: Int = 2

メソッドfを多相関数オブジェクトに変換することはできませんg。ご覧のとおり、 の推論された型gは実際Function1[Nothing, Nothing]には であり、これは役に立ちません。ただし、型ヒントを使用すると、引数h: Function1[Int,Int]に対して期待どおりに機能するように構築できます。Int

于 2013-03-07T06:58:28.843 に答える
8

あなたが言うように、あなたの例ではあなたが必要としているのはtoString方法だけであり、それでAny通常の解決策になるでしょう。Listただし、タプル内のすべての要素などに型コンストラクターを適用する場合など、より高いランクの型を使用できるようにする必要があります。

他の回答が述べているように、これを直接サポートすることはできませんが、それをエンコードするための比較的優れた方法があります。

trait ~>[A[_],B[_]] {
  def apply[X](a : A[X]) : B[X]
}

type Id[A] = A //necessary hack

object newList extends (Id ~> List) {
  def apply[X](a : Id[X]) = List(a)
}

def tupleize[A,B, F[_]](f : Id ~> F, a : A, b : B) = (f(a), f(b))

tupleize(newList, 1, "Hello") // (List(1), List(Hello))
于 2013-03-07T09:54:44.967 に答える
1

longStringFunction以下のように定義されているので、値は特定の型を持つ必要があります。

val longStringFunction: (T) => Boolean = (obj: T) => obj.toString.length > 7

ただし、関数オブジェクトをメソッドで再利用できます。

scala> val funObj: Any => Boolean = _.toString.size > 7
funObj: Any => Boolean = <function1>

scala> def typedFunction[T]: T => Boolean = funObj
typedFunction: [T]=> T => Boolean

scala> val f1 = typedFunction[String]
f1: String => Boolean = <function1>

scala> val f2 = typedFunction[Int]
f2: Int => Boolean = <function1>

scala> f1 eq f2
res0: Boolean = true

これは type の反変であるためtrait Function1[-T1, +R]機能しますT1

于 2013-03-07T08:45:33.640 に答える
1

scala では、関数の値はパラメトリックにモノモーフィックです (メソッドはポリモーフィックです)。

Shapeless ライブラリは、HList やその他の多くの機能にマップできる多態的な関数値を導入します。

次の参照を考慮してください: http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/ http://www.chuusai.com/2012/05/10/shapeless多形関数値-2/

于 2014-12-26T10:15:50.177 に答える