7

シンボルの型class A[_]またはのdef a[_](x: Any)型には、本体で参照できない型パラメーターがあるため、それがどこで役立つのか、なぜコンパイルされるのかわかりません。この型パラメーターを参照しようとすると、エラーがスローされます。

scala> class A[_] { type X = _ }
<console>:1: error: unbound wildcard type
       class A[_] { type X = _ }
                             ^

scala> def a[_](x: Any) { type X = _ }
<console>:1: error: unbound wildcard type
       def a[_](x: Any) { type X = _ }
                                   ^

そのようなタイプがScalaでユースケースを持っているかどうか誰か教えてもらえますか? 正確に言うと、型パラメーターの存在型またはより高度な種類の型を意味するのではなく[_]、完全な型パラメーター リストを形成するわずかな型のみを意味します。

4

4 に答える 4

4

私はそれがここで何を意味するのかについていくつかのカジュアルなアイデアを持っていました:

https://issues.scala-lang.org/browse/SI-5606

些細なユースケースに加えて、私が本当に気にしないのでコンパイラに名前を付けるように頼む(クラスを実装するときに後で名前を付けるかもしれませんが)、これはまだ私に便利だと思います:

もう1つの使用例は、型推論の改善により不要になるため、型パラメーターが非推奨になる場合です。

trait T[@deprecated("I'm free","2.11") _, B <: S[_]] 

次に、仮想的に、の使用について警告することはできますが、警告することはできT[X, Y]ませんT[_, Y]

注釈が前(値パラメータースタイル)になるのか後(タイプスタイルの注釈)になるのかは明らかではありませんが。

[編集:「コンパイルする理由」:case class Foo[_](i: Int)2.9.2でもうまくクラッシュする]

于 2012-10-09T20:48:18.437 に答える
4

期待した答えが得られなかったので、これをscala-languageに持ってきました。

Lars Hupel からの回答をここに貼り付けます (したがって、すべてのクレジットは彼に適用されます)。

ここで突き刺します。型メンバーについて話すと、この機能の使用法が明確になると思います。

次の特性を実装する必要があるとします。

trait Function {
  type Out[In]
  def apply[In](x: In): Out[In]
}

これは、戻り値の型が入力型に依存する (ジェネリック) 関数になります。インスタンスの例:

val someify = new Function {
  type Out[In] = Option[In]   def
  apply[In](x: In) = Some(x)
}

someify(3) res0: Some[Int] = Some(3)

ここまでは順調ですね。では、定数関数をどのように定義しますか?

val const0 = new Function {
  type Out[In] = Int
  def apply[In](x: In) = 0
}

const0(3) res1: const0.Out[Int] = 0

(型const0.Out[Int]は と同等ですがInt、そのようには出力されません。)

type パラメータInが実際には使用されていないことに注意してください。したがって、次のように記述できます_

val const0 = new Function {
  type Out[_] = Int
  def apply[In](x: In) = 0
}

_その場合は、実際には参照できない型パラメーターの名前と考えてください。これは、値レベルと同じように、パラメーターを気にしない型レベルの関数です。

(_: Int) => 3 res4: Int => Int = <function1>

ただし…</p>

type Foo[_, _] = Int
<console>:7: error: _ is already defined as type _
       type Foo[_, _] = Int

それを次のものと比較してください。

(_: Int, _: String) => 3 res6: (Int, String) => Int = <function2>

したがって、結論として:

type F[_] = ConstType // when you have to implement a type member def
foo[_](...) // when you have to implement a generic method but don't
            // actually refer to the type parameter (occurs very rarely)

あなたが言及した主なものは、class A[_]それと完全に対称的ですが、実際のユースケースはありません。

このことを考慮:

trait FlyingDog[F[_]] { def swoosh[A, B](f: A => B, a: F[A]): F[B] }

FlyingDogここで、単純な古いのインスタンスを作成したいとしますclass A

new FlyingDog[A] { ... }
// error: A takes no type parameters, expected: one
// (aka 'kind mismatch')

次の 2 つの解決策があります。

  1. 代わりに宣言class A[_]します。(そうしないでください。)

  2. タイプ ラムダを使用します。

    new FlyingDog[({ type λ[α] = A })#λ]
    

あるいは

new FlyingDog[({ type λ[_] = A })#λ]
于 2012-10-10T10:31:40.157 に答える
2

Scalaの下線は、実存的なタイプ、つまり未知のタイプのパラメーターを示します。これには、主に2つの使用法があります。

  • タイプパラメータを気にしないメソッドに使用されます
  • これは、1つの型パラメーターが型コンストラクターであることを表現したいメソッドに使用されます。

型コンストラクターは基本的に、具体的な型を構築するために型パラメーターを必要とするものです。たとえば、次の署名を取得できます。

def strangeStuff[CC[_], B, A](b:B, f: B=>A): CC[A] 

これは、CC[_]たとえばaのList[_]場合List[A]、Bと関数から開始する関数B=>Aです。

なぜそれが役立つのでしょうか?そのメカニズムを暗黙的および型クラスと一緒に使用すると、コンパイラーの推論のおかげで、いわゆるアドホック多相性を得ることができます。

たとえば、より種類の多いタイプがあるとします。Container[_]具体的な実装の階層があります: BeautifulContainer[_]、、。コンテナを構築するには、BigContainer[_]SmallContainer[_]

trait ContainerBuilder[A[_]<:Container[_],B] { 

def build(b:B):A[B]

}

つまり、基本的にContainerBuilderは、特定のタイプのコンテナーに対してA[_]がBを使用してA[B]を構築できるものです。

それは役に立ちますか?次のような別の場所で関数が定義されている可能性があることを想像できます。

def myMethod(b:B)(implicit containerBuilder:ContainerBuilder[A[_],B]):A[B] = containerBuilder.build(b)

そして、あなたのコードであなたはするかもしれません:

val b = new B()
val bigContainer:BigContainer[B] = myMethod(b)
val beautifulContainer:BeautifulContainer[B] = myMethod(b)

実際、コンパイラはmyMethodの必要な戻り型を使用して、必要な型の制約を満たす暗黙的なものを探し、暗黙的に使用可能な必要な制約を満たすContainerBuilderがない場合は、コンパイルエラーをスローします。

于 2012-10-08T11:54:18.467 に答える
1

これは、型パラメーターを気にせずにパラメーター化された型のインスタンスを処理する場合に役立ちます。

trait Something[A] {
  def stringify: String
}

class Foo extends Something[Bar] {
  def stringify = "hop"
}

object App {
  def useSomething(thing: Something[_]) :String = {
    thing.stringify
  }
}
于 2012-10-08T11:32:05.657 に答える