2012-10-08 6 views
7

シンボルのタイプclass A[_]またはdef a[_](x: Any)には、本体で参照できないタイプパラメータがあります。したがって、それが役に立つ場所とコンパイルする理由はわかりません。 1は、このタイプのパラメータを参照しようとすると、エラーがスローされます。`class A [_]`は何のために便利ですか?

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でユースケースを持っている場合、誰かが私に言うことはできますか?厳密に言えば、型パラメータに存在する型または上位型の型を意味するのではなく、完全型パラメータリストを構成するlitte [_]の型だけを意味します。

答えて

4

私は私が期待し答えを取得していないので、私はscala-languageにこれをもたらしました。

私はここでほとんど私が知りたかったかを説明ラースHupel(そう、すべてのクレジットは彼に適用されます)、からの回答を貼り付けます。私はそれをここで刺しを与えるつもりだ

を。私は型のメンバーについて話すとき、この機能の使用が をクリアすると思います。

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

は、この戻り値の型が 入力タイプによって異なります(一般的な)関数のようになります。

では、次の特性を実装する必要があるとします。例の1つの例:

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> 

除いて...

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] } 

は今、あなたはあなたの平野 古いclass AためFlyingDogのインスタンスを作成するとします。

  1. 代わりclass A[_]を宣言します。

    は、二つの解決策があります。 (。それをしないでください)

  2. 型ラムダ使用する:あなたがここで意味することはないが実存タイプです

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

あるいは

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

これは、型パラメーターの注意を払わずにパラメーター化された型のインスタンスを処理する場合に便利です。

trait Something[A] { 
    def stringify: String 
} 

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

object App { 
    def useSomething(thing: Something[_]) :String = { 
    thing.stringify 
    } 
} 
+1

を私が言ったことの意味。 – sschaef

2

Scalaではアンダースコアが2つの主な用途がある未知のタイプのパラメータ、すなわち、実存タイプを示します。これは、型パラメータを気にしない方法で使用される

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

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

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

これは、いくつかのCC[_]ため、例えばList[_]ため、B及び機能B=>Aから出発List[A]を作成する機能です。

なぜ便利でしょうか?このメカニズムをimplicitsやtypeclassesと一緒に使うと、コンパイラの推論のおかげでアドホック多形性を得ることができます。

あなたには、いくつかのより高いkindedタイプを持っ例えば想像:Container[_]具体的な実装の階層構造を持つ:BeautifulContainer[_]BigContainer[_]SmallContainer[_]。コンテナを構築するには次のものが必要

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

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

} 

そこで、基本的ContainerBuilderはそれは次のようになり

しばらくB.を使用して、コンテナAの特定のタイプのために[_] 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がない場合、コンパイルエラーをスローします。

+2

タイプパラメータとして実在型以上の種別型を意味するわけではありませんでしたが、存在するが参照できない型パラメータを意味していました。 – sschaef

+0

正しい答えは前のものです – Edmondo1984

+0

前のどれですか?削除されたものは? – sschaef

4

私はそれがここで意味するかもしれないことについて、いくつかのカジュアルなアイデアを持っていた:私は本当に私は多分ものの(気にしないので、名前を構成するためにコンパイラを求めて、些細なユースケースのほかに

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

を私はクラスを実装する際にっ)後でそれを名前を付け、この1はまだとして有用な私を打つ:

型推論で 改善は、それが余計にするため、typeのparamが廃止されている別のユースケースがあります。

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

次に、仮に、 1はT[X, Y]なくT[_, Y]の使用に警告することができます。

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

は、[編集:「なぜそれがコンパイル」:case class Foo[_](i: Int)はまだ2.9.2にうまくクラッシュ]

関連する問題