Spec2.8Chap3a

「Spec2.8Chap3a」の編集履歴(バックアップ)一覧はこちら

Spec2.8Chap3a」(2011/02/23 (水) 18:29:25) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

#setmenu2(spec2.8-r-menu) * 第 3 章 型 (Types) &bold(){構文:} #co(){ --------------- bgn-code} Type ::= FunctionArgTypes '=>' Type | InfixType [ExistentialClause] FunctionArgTypes ::= InfixType | '(' [ ParamType {',' ParamType } ] ')' ExistentialClause ::= 'forSome' '{' ExistentialDcl {semi ExistentialDcl} '}' ExistentialDcl ::= 'type' TypeDcl | 'val' ValDcl InfixType ::= CompoundType {id [nl] CompoundType} CompoundType ::= AnnotType {'with' AnnotType} [Refinement] | Refinement AnnotType ::= SimpleType {Annotation} SimpleType ::= SimpleType TypeArgs | SimpleType '#' id | StableId | Path '.' 'type' | '(' Types ')' TypeArgs ::= '[' Types ']' Types ::= Type {',' Type} #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-show0} We distinguish between first-order types and type constructors, which take type parameters and yield types. A subset of first-order types called value types represents sets of (first-class) values. Value types are either concrete or abstract. #co(){----------------------------------------------------- end-show0} 一階型と、パラメータを指定して型を生み出す型コンストラクタとを区別します。 &strong(){値型(value types)}と呼ばれる一階型の部分集合は、 (first class:第一級の)値の集合を表します。 値型は&strong(){具象あるいは抽象}のいずれかです。 #co(){----------------------------------------------------- bgn-hide0} Every concrete value type can be represented as a class type, i.e. a type designator (§3.2.3) that refers to a a class or a trait(*1)(§5.3), or as a compound type (§3.2.7) representing an intersection of types, possibly with a refinement (§3.2.7) that further constrains the types of its members. Abstract value types are introduced by type parameters (§4.4) and abstract type bindings (§4.3). Parentheses in types can be used for grouping. #co(){----------------------------------------------------- end-hide0} すべての具象値型は、&strong(){クラス型}として表せます。すなわち、 クラスやトレイト(*1)(&link_anchor(5.3,page=Spec2.8Chap5c2){§5.3}) を参照する型指定子 (&link_anchor(3.2.3,page=Spec2.8Chap3a){§3.2.3})、 あるいは、型の論理積(intersection)を表す&strong(){複合型} (&link_anchor(3.2.7,page=Spec2.8Chap3a){§3.2.7})としてです。 複合型には、そのメンバーの型にさらなる制約を与える細別 (refinement &link_anchor(3.2.7,page=Spec2.8Chap3a){§3.2.7}) を加えることができます。 抽象値型は、型パラメータ(&link_anchor(4.4,page=Spec2.8Chap4a){§4.4}) と抽象型束縛(&link_anchor(4.3,page=Spec2.8Chap4a){§4.3})によって導入されます。 型の中では、丸括弧をグルーピングのために使えます。 #co(){----------------------------------------------------- bgn-hide0} (*1) We assume that objects and packages also implicitly define a class (of the same name as the object or package, but inaccessible to user programs). #co(){----------------------------------------------------- end-hide0} (*1) 我々はオブジェクトとパッケージも暗黙のうちに (ユーザープログラムはアクセスできない、 オブジェクトあるいはパッケージと同じ名前の) クラスを定義すると考えます。 #co(){----------------------------------------------------- bgn-hide0} Non-value types capture properties of identifiers that are not values (§3.3). For example, a type constructor (§3.3.3) does not directly specify a type of values. However, when a type constructor is applied to the correct type arguments, it yields a first-order type, which may be a value type. #co(){----------------------------------------------------- end-hide0} 非値型は、値でない識別子のプロパティを取り込みます (&link_anchor(3.3,page=Spec2.8Chap3b){§3.3})。 例えば、型コンストラクタ (&link_anchor(3.3.3,page=Spec2.8Chap3b){§3.3.3}) は直接には値の型を指定しません。 しかし、型コンストラクタが正しい型引数に適用されれば、 それは値型であろう一階型をもたらします。 #co(){----------------------------------------------------- bgn-hide0} Non-value types are expressed indirectly in Scala. E.g., a method type is described by writing down a method signature, which in itself is not a real type, although it gives rise to a corresponding method type (§3.3.1). Type constructors are another example, as one can write type Swap[m[_, _], a,b] = m[b, a], but there is no syntax to write the corresponding anonymous type function directly. #co(){----------------------------------------------------- end-hide0} 非値型は Scalaでは間接的に表現されます。 例えば、 メソッド型はメソッドのシグニチャを書き出して記述できますが、 それ自身は実際の型でないけれども、 対応するメソッド型(&link_anchor(3.3.1,page=Spec2.8Chap3b){§3.3.1}) を引き起こします。 型コンストラクタは他の例です。型を Swap[m[_, _], a,b] = m[b, a] と書けますが、 しかし、対応する無名の型関数を直接的に書くための構文はありません。 &br() &br() &aname(3.1,option=nolink){ } ** 3.1 パス (Paths) &bold(){構文:} #co(){ --------------- bgn-code} Path ::= StableId | [id '.'] this StableId ::= id | Path '.' id | [id '.'] 'super' [ClassQualifier] '.' id ClassQualifier ::= '[' id ']' #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Paths are not types themselves, but they can be a part of named types and in that function form a central role in Scala's type system. #co(){----------------------------------------------------- end-hide0} パスそれ自身は型ではありません。しかしそれは、名前付きの型(named type) の一部であり、その機能は Scala 型システムの中で中心的役割を果たします。 #co(){----------------------------------------------------- bgn-hide0} A path is one of the following. - The empty path (which cannot be written explicitly in user programs). - C.this, where C references a class. The path this is taken as a shorthand for C.this ,where C is the name of the class directly enclosing the reference. #co(){----------------------------------------------------- end-hide0} パスは次のうちの1つです。 - 空のパス (ユーザープログラム中では、明示的には書けません)。 - C.this。ここで C はクラスを参照します。パス this は C.this の略記表現として解釈されます。ここで C は、参照を直接囲むクラスの名前です。 #co(){----------------------------------------------------- bgn-show0} - p.x where p is a path and x is a stable member of p. Stable members are packages or members introduced by object definitions or by value definitions of non-volatile types (§3.6). - C.super.x or C.super[M].x where C references a class and x references a stable member of the super class or designated parent class M of C. The prefix super is taken as a shorthand for C.super where C is the name of the class directly enclosing the reference. #co(){----------------------------------------------------- end-show0} - p.x。ここで p はパス、x は p の安定メンバー。 &strong(){安定メンバー(stable members)}とは、オブジェクト定義によってあるいは非 volatile 型の値定義によって導入されたメンバーあるいはパッケージのことです(&link_anchor(3.6,page=Spec2.8Chap3b){§3.6})。 - C.super.x あるいは C.super[M].x。 ここで C はクラスを参照し、x は、スーパークラスあるいは C の指定された親クラス M の、安定メンバーを参照します。 前置子 super は、C.super の略記表現として解釈されます。 ここで C は、参照を直接囲むクラスの名前です。 #co(){----------------------------------------------------- bgn-hide0} A stable identifier is a path which ends in an identifier. #co(){----------------------------------------------------- end-hide0} &strong(){安定識別子(stable identifier)}とは、最後が識別子で終わるパスです。 &br() &br() &aname(3.2,option=nolink){ } ** 3.2 値型 (Value Types) #co(){----------------------------------------------------- bgn-hide0} Every value in Scala has a type which is of one of the following forms. #co(){----------------------------------------------------- end-hide0} Scala のすべての値は、次の形のどれか 1 つをとる型を持っています。 &br() &br() &aname(3.2.1,option=nolink){ } *** 3.2.1 シングルトン型 (Singleton Types) &bold(){構文:} #co(){ --------------- bgn-code} SimpleType ::= Path '.' type #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A singleton type is of the form p.type, where p is a path pointing to a value expected to conform (§6.1) to scala.AnyRef. The type denotes the set of values consisting of null and the value denoted by p . A stable type is either a singleton type or a type which is declared to be a subtype of trait scala.Singleton. #co(){----------------------------------------------------- end-hide0} シングルトン型は p.type の形の型であり、ここで p はパスで、 scala.AnyRefに適合する (&link_anchor(6.1,page=Spec2.8Chap6a){§6.1})ことが要請される値を指し示します。 この型は、null と p で示される値からなる集合を表します。 &strong(){安定型(stable type)}とは、シングルトン型あるいは、 トレイト scala.Singleton のサブ型 (subtype) であると宣言された型、 のいずれかです。 &br() &br() &aname(3.2.2,option=nolink){ } *** 3.2.2 型射影 (Type Projection) &bold(){構文:} #co(){ --------------- bgn-code} SimpleType ::= SimpleType '#' id #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A type projection T#x references the type member named x of type T . #co(){----------------------------------------------------- end-hide0} 型射影 T#x は、型 T の x という名前の型メンバーを参照します。 &br() &br() &aname(3.2.3,option=nolink){ } *** 3.2.3 型指定子 (Type Designators) &bold(){構文:} #co(){ --------------- bgn-code} SimpleType ::= StableId #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A type designator refers to a named value type. It can be simple or qualified. All such type designators are shorthands for type projections. #co(){----------------------------------------------------- end-hide0} 型指定子は、名前付きの値型を参照します。 それは単純名であるか、 あるいは限定修飾されます。 そのような型指定子はすべて、型射影の略記表現です。 #co(){----------------------------------------------------- bgn-hide0} Specifically, the unqualified type name t where t is bound in some class, object, or package C is taken as a shorthand for C.this.type#t . If t is not bound in a class, object, or package, then t is taken as a shorthand for ε.type#t . A qualified type designator has the form p.t where p is a path (§3.1) and t is a type name. Such a type designator is equivalent to the type projection p.type#t . #co(){----------------------------------------------------- end-hide0} 特に、限定修飾されていない型名 t は、C.this.type#t の略記表現として解釈されます。 ここで t はあるクラス、オブジェクト、 あるいはパッケージ C 内で束縛されているものとします。 もし t がクラス、オブジェクト、あるいはパッケージ内で束縛されていないなら、 t は ε.type#t の略記表現と解釈されます。 限定修飾された型指定子は、p.t の形をしています。 ここで p はパス(&link_anchor(3.1,page=Spec2.8Chap3a){§3.1})、t は型名です。 そのような型指定子は型射影 p.type#t に等価です。 &br() &bold(){Example 3.2.1} #co(){----------------------------------------------------- bgn-hide0} Some type designators and their expansions are listed below. We assume a local type parameter t , a value maintable with a type member Node and the standard class scala.Int, #co(){----------------------------------------------------- end-hide0} 次は、いくつかの型指定子とそれらの展開をリストしています。 ここで、ローカルな型パラメータ t、型メンバー Nodeを持つ値 maintable、 標準的なクラス scala.Int があると仮定します。 #co(){ --------------- bgn-code} t ε.type#t Int scala.type#Int scala.Int scala.type#Int data.maintable.Node data.maintable.type#Node #co(){ --------------- end-code} &br() &br() &aname(3.2.4,option=nolink){ } *** 3.2.4 パラメータ化された型 (Parameterized Types) &bold(){構文:} #co(){ --------------- bgn-code} SimpleType ::= SimpleType TypeArgs TypeArgs ::= '[' Types ']' #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A parameterized type T[U1,...,Un] consists of a type designator T and type parameters U1,...,Un where n>=1. T must refer to a type constructor which takes n type parameters a1,...,an . Say the type parameters have lower bounds L1,...,Ln and upper bounds U1,...,Un . The parameterized type is well-formed if each actual type parameter conforms to its bounds, i.e. σLi <: Ti <: σUi where σ is the substitution [a1 := T1,...,an := Tn]. #co(){----------------------------------------------------- end-hide0} パラメータ化された型 T[U1,...,Un] は、型指定子 T と 型パラメータ U1,...,Un (n >= 1) から成ります。 T は、n 個の型パラメータ a1,...,an をとる型コンストラクタを参照していなければなりません。 例えば、型パラメータが下限境界 L1,...,Ln と上限境界 U1,...,Un を持っているとします。 もし、それぞれ実際の型パラメータがその&strong(){両境界に適合する}なら、 つまり σLi <: Ti <: σUi なら (ここで σは置換[a1 := T1,...,an := Tn])、 このパラメータ化された型は正しい形(well formed)です。 &br() &bold(){Example 3.2.2} 次のような部分的な型定義が与えられているとします。 #co(){ --------------- bgn-code} class TreeMap[A <: Comparable[A], B] { ... } class List[A] { ... } class I extends Comparable[I] { ... } class F[M[_], X] { ... } class S[K <: String] { ... } class G[M[ Z <: I ], I] { ... } #co(){ --------------- end-code} このとき、次のパラメータ化された型は正しい形です。 #co(){ --------------- bgn-code} TreeMap[I, String] List[I] List[List[Boolean]] F[List, Int] G[S, String] #co(){ --------------- end-code} &br() &bold(){Example 3.2.3} 例3.2.2の型定義が与えられているとき、次の型は不正な形(ill-formed)です。 #co(){ --------------- bgn-code} TreeMap[I] // 不正: パラメータ数誤り。 TreeMap[List[I], Int] // 不正: 型パラメータが境界外。 F[Int, Boolean] // 不正: Int は型コンストラクタではない。 F[TreeMap, Int] // 不正: TreeMap は 2 つのパラメータをとるが、 // F は 1 パラメータのコンストラクタである。 G[S, Int] // 不正: S は、Stringに適合するパラメータを含み、 // G は、Intに適合するパラメータをもつ // 型コンストラクタが要請される。 #co(){ --------------- end-code} &br() &br() &aname(3.2.5,option=nolink){ } *** 3.2.5 タプル型 &bold(){構文:} #co(){ --------------- bgn-code} SimpleType ::= '(' Types ')' #co(){ --------------- end-code} タプル型 (T1,...,Tn) は、クラス scala.Tuplen[T1,...,Tn] のエイリアスです。 ここで n >= 2。 タプルクラスはケースクラスであり、 セレクター _1, ..., _n を使ってそのフィールドにアクセスできます。 #co(){----------------------------------------------------- bgn-hide0} Their functionality is abstracted in a corresponding Product trait. The n-ary tuple class and product trait are defined at least as follows in the standard Scala library (they might also add other methods and implement other traits). #co(){----------------------------------------------------- end-hide0} それらの関数は、対応する Product トレイト内にまとめられています。 n 項タプルクラスと product トレイトは、標準的な Scala ライブラリにおいて、 少なくとも次のように定義されています (他のメソッドも加え、また、他のトレイトも実装しているかもしれません)。 #co(){ --------------- bgn-code} case class Tuplen[+T1, ..., +Tn](_1: T1, ..., _n : Tn) extends Productn[T1, ..., Tn] {} trait Productn[+T1, +T2, +Tn] { override def arity = n def _1: T1 ... def _n :Tn } #co(){ --------------- end-code} &br() &br() &aname(3.2.6,option=nolink){ } *** 3.2.6 アノテーション型 (Annotated Types) &bold(){構文:} #co(){ --------------- bgn-code} AnnotType ::= SimpleType {Annotation} #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} An annotated type T a1...an attaches annotations a1,...,an to the type T (§11). #co(){----------------------------------------------------- end-hide0} アノテーション型 T a1...an は、型 T にアノテーション a1,...,an を付加します (&link_anchor(11,page=Spec2.8Chap11a){§11})。 &br() &bold(){Example 3.2.4} 次の型は、文字列型に @suspendable@ アノテーションを付加します: #co(){ --------------- bgn-code} String @suspendable #co(){ --------------- end-code} &br() &br() &aname(3.2.7,option=nolink){ } *** 3.2.7 複合型 (Compound Types) (訳注:複合型については [[A Tour of Scala:Compound Types>http://www.scala-lang.org/node/110]] に簡単な説明があります) &bold(){構文:} #co(){ --------------- bgn-code} CompoundType ::= AnnotType {'with' AnnotType} [Refinement] | Refinement Refinement ::= [nl] '{' RefineStat {semi RefineStat} '}' RefineStat ::= Dcl | 'type' TypeDef | #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A compound type T1 with ... with Tn {R } represents objects with members as given in the component types T1,...,Tn and the refinement {R }. A refinement {R} contains declarations and type definitions. If a declaration or definition overrides a declaration or definition in one of the component types T1,...,Tn , the usual rules for overriding (§5.1.4) apply; otherwise the declaration or definition is said to be "structural" (*2) . #co(){----------------------------------------------------- end-hide0} 複合型 T1 with ... with Tn {R} は、構成要素型 T1,...,Tn と細別 {R} で与えられたメンバーをもつオブジェクトを表わします。 細別 {R} は、宣言と型定義を含みます。 もし宣言あるいは定義が、構成要素型 T1,...Tn の 1 つの中の宣言あるいは定義をオーバライドするなら、 オーバライドの通常の規則が適用されます (&link_anchor(5.1.4,page=Spec2.8Chap5a){§5.1.4}); そうでないなら、宣言あるいは定義は「構造的」と言われます(*2)。 #co(){----------------------------------------------------- bgn-hide0} (*2) A reference to a structurally defined member (method call or access to a value or variable) may generate binary code that is significantly slower than an equivalent code to a non-structural member. #co(){----------------------------------------------------- end-hide0} (*2) 構造的に定義されたメンバーへの参照(メソッド呼び出しあるいは、 値/変数へのアクセス)は、非構造的メンバーを参照する等価なコードより、 際立って遅いバイナリコードを生成することがあります。 #co(){----------------------------------------------------- bgn-hide0} Within a method declaration in a structural refinement, the type of any value parameter may only refer to type parameters or abstract types that are contained inside the refinement. That is, it must refer either to a type parameter of the method itself, or to a type definition within the refinement. This restriction does not apply to the function's result type. #co(){----------------------------------------------------- end-hide0} 構造的な細別内のメソッド宣言では、すべての値パラメータの型は、その細別内に 含まれる型パラメータあるいは抽象型だけを参照できます。 すなわち、 メソッド自身の型パラメータへの参照であるか、あるいは、 細別内の型定義への参照のいずれかです。 この制限は関数の結果型には適用されません。 もし細別が与えられていなければ、空の細別が暗黙のうちに加えられます。 つまり、T1 with ... with Tn は、T1 with ... with Tn {} の略記表現です。 複合型は、先行する構成要素型のない、細別 {R} だけから成ることもあります。 そのような型は AnyRef {R} に等価です。 &br() &bold(){Example 3.2.5} 次の例は、関数のパラメータ型が構造的宣言をもつ細別を含む場合の、 宣言方法と使い方を示しています。 #co(){ --------------- bgn-code} case class Bird (val name: String) extends Object { def fly(height: Int) = ... ... } case class Plane (val callsign: String) extends Object { def fly(height: Int) = ... ... } def takeoff( runway: Int, r: { val callsign: String; def fly(height: Int) }) = { tower.print(r.callsign + " requests take-off on runway " + runway) tower.read(r.callsign + " is clear for take-off") r.fly(1000) } val bird = new Bird("Polly the parrot"){ val callsign = name } val a380 = new Plane("TZ-987") takeoff(42, bird) takeoff(89, a380) #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Although Bird and Plane do not share any parent class other than Object, the parameter r of function takeoff is defined using a refinement with structural declarations to accept any object that declares a value callsign and a fly function. #co(){----------------------------------------------------- end-hide0} Bird と Plane は Object 以外の親クラスを共有していませんが、 関数 takeoff のパラメータ r は、構造的宣言の細別を使って定義されていて、 値 callsign と fly 関数を宣言する任意のオブジェクトを受けつけます。 &br() &br() &aname(3.2.8,option=nolink){ } *** 3.2.8 中置型 (Infix Types) &bold(){構文:} #co(){ --------------- bgn-code} InfixType ::= CompoundType {id [nl] CompoundType} #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} An infix type T1 op T2 consists of an infix operator op which gets applied to two type operands T1 and T2 . The type is equivalent to the type application op[T1 , T2]. #co(){----------------------------------------------------- end-hide0} 中置型 T1 op T2 は、2 つのオペランド型 T1 と T2 へ適用される中置演算子 op からなります。 この型は型適用 op[T1,T2] に等価です。 中置演算子 op には、* 以外の任意の識別子が使えます。 * は 反復パラメータ型(&link_anchor(4.6.2,page=Spec2.8Chap4b){§4.6.2}) を表す後置修飾子として予約されています。 #co(){----------------------------------------------------- bgn-hide0} All type infix operators have the same precedence; parentheses have to be used for grouping. The associativity (§6.12) of a type operator is determined as for term operators : type operators ending in a colon ':' are right-associative; all other operators are left-associative. #co(){----------------------------------------------------- end-hide0} すべての中置型演算子は同じ優先順位を持っています; グルーピングには丸括弧を使われなければなりません。 型演算子の結合性(&link_anchor(6.12,page=Spec2.8Chap6b){§6.12})は 項演算子(term operator)については決まっています。 ':'で終わる型演算子は右結合です。他のすべての演算子は左結合です。 #co(){----------------------------------------------------- bgn-hide0} In a sequence of consecutive type infix operations t0 op1 t1 op2 ... opn tn , all operators op1,...,opn must have the same associativity. If they are all left-associative, the sequence is interpreted as (... (t0 op1 t1 ) op2 ...) opn tn , otherwise it is interpreted as t0 op1 (t1 op2 (... opn tn ) ...). #co(){----------------------------------------------------- end-hide0} 連続する中置型演算のシーケンス t0 op1 t1 op2 ... opn tn では、 すべての演算子 op1,...,opn が同じ結合性を持っていなくてはなりません。 もしそれらがすべて左結合なら、シーケンスは (... (t0 op1 t1 ) op2 ...) opn tn と解釈され、そうでなければ t0 op1 (t1 op2 (... opn tn ) ...) と解釈されます。 &br() &br() &aname(3.2.9,option=nolink){ } *** 3.2.9 関数型 (Function Types) &bold(){構文:} #co(){ --------------- bgn-code} Type ::= FunctionArgs '=>' Type FunctionArgs ::= InfixType | '(' [ ParamType {',' ParamType } ] ')' #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} The type (T1,...,Tn ) => U represents the set of function values that take arguments of types T1,...,Tn and yield results of type U . In the case of exactly one argument type T => U is a shorthand for (T ) => U . An argument type of the form => T represents a call-by-name parameter (§4.6.1) of type T . #co(){----------------------------------------------------- end-hide0} 型 (T1,...,Tn) => U は、型 T1,...,Tn を引数にとり、型 U の結果をもたらす関数値の集合を表します。引数が正確に 1 つだけの場合は、 型 T => U は (T) => U の略記表現です。 形が => T の引数型は、型 T の名前呼出しパラメータ (&link_anchor(4.6.1,page=Spec2.8Chap4b){§4.6.1})を表します。 #co(){----------------------------------------------------- bgn-hide0} Function types associate to the right, e.g. S => T => U is the same as S => (T => U ). Function types are shorthands for class types that define apply functions. Specifically , the n-ary function type (T1,...,Tn ) => U is a shorthand for the class type Functionn[T1,...,Tn ,U]. Such class types are defined in the Scala library for n between 0 and 9 as follows. #co(){----------------------------------------------------- end-hide0} 関数型は右へ結合します。例えば、S => T => U は S => (T => U) と同じです。 関数型は、apply 関数を定義するクラス型の略記表現です。 特に、n 項関数型 (T1,...,Tn) => U は、クラス型 Functionn[T1,...,Tn,U] の略記表現です。 このようなクラス型は、0 以上 9 以下の n に対して Scala ライブラリ中で、次のように定義されています。 #co(){ --------------- bgn-code} package scala trait Functionn[-T1,...,-Tn , +R] { def apply(x1 : T1,...,xn : Tn ): R override def toString = "<function>" } #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Hence, function types are covariant (§4.5) in their result type and contravariant in their argument types. #co(){----------------------------------------------------- end-hide0} したがって、関数型は、その結果型については共変 (&link_anchor(4.5,page=Spec2.8Chap4a){§4.5})、その引数型については反変です。 &br() &br() &aname(3.2.10,option=nolink){ } *** 3.2.10 存在型 (Existential Types) &bold(){構文:} #co(){ --------------- bgn-code} Type ::= InfixType ExistentialClauses ExistentialClauses ::= 'forSome' '{' ExistentialDcl {semi ExistentialDcl} '}' ExistentialDcl ::= 'type' TypeDcl | 'val' ValDcl #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} An existential type has the form T forSome { Q } ,where Q is a sequence of type declarations §4.3. Let t1[tps1] >: L1 <: U1,...,tn[tpsn] >: Ln <: Un be the types declared in Q (any of the type parameter sections [tpsi] might be missing). The scope of each type ti includes the type T and the existential clause Q. The type variables ti are said to be bound in the type T forSome { Q }. Type variables which occur in a type T but which are not bound in T are said to be free in T . #co(){----------------------------------------------------- end-hide0} 存在型は、T forSome { Q } の形をしています。ここで Q は型宣言 (&link_anchor(4.3,page=Spec2.8Chap4a){§4.3})の並びです。 t1[tps1] >: L1 <: U1,...,tn[tpsn] >: Ln <: Un を Q 内で宣言された型であるとします (型パラメータ部 [tpsi] のどれかが欠けていても構いません)。 各型 ti のスコープは、型 T と存在節 Q を含みます。 型変数 ti は、型 T forSome { Q } 内で&strong(){束縛}されていると言われます。 型 T の中に現れるけれど T 内で束縛されない型変数は、 T 内で&strong(){自由(free)}であると言われます。 #co(){----------------------------------------------------- bgn-hide0} A type instance of T forSome { Q } is a type σT , where σ is a substitution over t1,...,tn such that, for each i , σLi <: σti <: σUi . The set of values denoted by the existential type T forSome { Q } is the union of the set of values of all its type instances . #co(){----------------------------------------------------- end-hide0} T forSome { Q }の&strong(){型インスタンス}は、型 σT です。 ここで σは、各 i に対し σLi <: σti <: σUi であるような t1,...,tn の置換とします。 存在型 T forSome { Q } によって示される値の集合は、 そのすべての型インスタンスの値の集合の和集合です。 #co(){----------------------------------------------------- bgn-hide0} A skolemization of T forSome { Q } is a type instance σT , where σ is the substitution [t´1/t1,...,t´n/tn] and each t´i is a fresh abstract type with lower bound σLi and upper bound σUi . #co(){----------------------------------------------------- end-hide0} T forSome { Q } の skolemization は、型インスタンス σT です。ここで σは、 [t´1/t1,...,t´n/tn] の置換で、各 t´i は、下限境界 σLi と上限境界 σUi をもつ新規の抽象型です。 &br() &bold(){簡略化規則} 存在型は、次の 4 つの等価規則に従います。 #co(){----------------------------------------------------- bgn-hide0} + Multiple for clauses in an existential type can be merged. E.g., T forSome { Q } forSome { Q´} is equivalent to T forSome { Q ; Q´}. + Unused quantifications can be dropped. E.g., T forSome { Q ; Q´} where none of the types defined in Q´ are referred to by T or Q, is equivalent to T forSome { Q }. + An empty quantification can be dropped. E.g., T forSome { } is equivalent to T . + An existential type T forSome { Q } ,where Q contains a clause type t[tps] >: L <: U is equivalent to the type T´ forSome { Q } ,where T´ results from T by replacing every covariant occurrence (§4.5) of t in T by U and by replacing every contravariant occurrence of t in T by L. #co(){----------------------------------------------------- end-hide0} + 存在型中の複数の for 節をマージできます。例えば、T forSome { Q } forSome { Q´} は T forSome { Q ; Q´} に等価です。 + 使われていない存在量化(quantification)を外すことができます。例えば、T forSome { Q ; Q´} は、T forSome { Q } に等価です。ただしここで Q´中で 定義されたどの型も、T あるいは Q によって参照されないものとします。 + 空の存在量化を外すことができます。例えば、T forSome { } は T に等価です。 + 存在型 T forSome { Q } (ここで Q は節 type t[tps] >: L <: U を含む) は、型 T´ forSome { Q } に等価です。ここで T´は、T 中で共変(&link_anchor(4.5,page=Spec2.8Chap4a){§4.5})として出現するすべての t を U で置き換え、T 中で反変として出現するすべての t を L で置き換えて得られるものです。 &br() &bold(){値の存在量化 (Existential Quantification over Values)} #co(){----------------------------------------------------- bgn-hide0} As a syntactic convenience, the bindings clause in an existential type may also contain value declarations val x : T . An existential type T forSome { Q ; val x : S ; Q´ } is treated as a shorthand for the type T´ forSome { Q ; type t <: S with Singleton; Q´ }, where t is a fresh type name and T´ results from T by replacing every occurrence of x.type with t . #co(){----------------------------------------------------- end-hide0} 文法上の便宜として、存在型中の束縛節に値宣言 val x : T を含めることができます。 存在型 T forSome { Q; val x : S ; Q´ } は、 型 T´ forSome { Q ; type t <: S with Singleton; Q´ } の略記表現として扱われます。ここで t は新たな型名で、 T´ は T 中に現れる x.type を t で置き換えて得られるものです。 &br() &bold(){存在型のプレースホルダ構文} &bold(){構文:} #co(){ --------------- bgn-code} WildcardType ::= '_' TypeBounds #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Scala supports a placeholder syntax for existential types. A wildcard type is of the form _ >: L <: U . Both bound clauses may be omitted. If a lower bound clause >: L is missing, >: scala.Nothing is assumed. If an upper bound clause <: U is missing , <: scala.Any is assumed. A wildcard type is a shorthand for an existentially quantified type variable, where the existential quantification is implicit. #co(){----------------------------------------------------- end-hide0} Scala は存在型のプレースホルダ構文をサポートしています。 &strong(){ワイルドカード型}は _ >: L <: U の形です。 それぞれの境界節はともに省略されるかもしれません。 もし下限境界節 >: L がないなら、>: scala.Nothing が想定されます。 もし上限境界節 <: U がないなら、<: scala.Any が想定されます。 ワイルドカード型は存在量化された型変数の略記表現です。 ここで、存在量化は暗黙的です。 #co(){----------------------------------------------------- bgn-hide0} A wildcard type must appear as type argument of a parameterized type. Let T = p.c[targs,T,targs´] be a parameterized type ,where targs,targs´ may be empty and T is a wildcard type _ >: L <: U . Then T is equivalent to the existential type #co(){----------------------------------------------------- end-hide0} ワイルドカード型は、パラメータ化された型の型引数として現われなくてはなりません。 いま、T = p.c[targs,T,targs´] をパラメータ化された型とします。 ここで targs,targs´ は空きでもよく、T はワイルドカード型 _ >: L <: U です。 このとき T は、次の存在型 #co(){ --------------- bgn-code} p.c[targs,t,targs´] forSome { type t >: L <: U } #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} where t is some fresh type variable. Wildcard types may also appear as parts of infix types (§3.2.8), function types (§3.2.9), or tuple types (§3.2.5). Their expansion is then the expansion in the equivalent parameterized type. #co(){----------------------------------------------------- end-hide0} と等価になります。ここで t は、ある新しい型変数とします。 ワイルドカード型は、 中置型(&link_anchor(3.2.8,page=Spec2.8Chap3a){§3.2.8})、 関数型(&link_anchor(3.2.9,page=Spec2.8Chap3a{§3.2.9})、 あるいはタプル型(&link_anchor(3.2.5,page=Spec2.8Chap3a){§3.2.5}) 等の一部にも現れることがあります。 それらの展開は、等価なパラメータ化された型内での展開となります。 &br() &bold(){Example 3.2.6} 次のクラス定義を仮定します。 #co(){ --------------- bgn-code} class Ref[T] abstract class Outer { type T } #co(){ --------------- end-code} 次は、存在型のいくつかの例です。 #co(){ --------------- bgn-code} Ref[T] forSome { type T <: java.lang.Number } Ref[x.T] forSome { val x: Outer } Ref[x_type# T] forSome { type x_type <: Outer with Singleton } #co(){ --------------- end-code} 上記リストの最後の 2 つの型は等価です。 最初の型をワイルドカード構文を使って書き換えると次のようになります。 #co(){ --------------- bgn-code} Ref[_ <: java.lang.Number] #co(){ --------------- end-code} &br() &bold(){Example 3.2.7} 型 List[List[_]] は、次の存在型に等価です。 #co(){ --------------- bgn-code} List[List[t] forSome { type t }] #co(){ --------------- end-code} &br() &bold(){Example 3.2.8} 次の共変型があるとします。 #co(){ --------------- bgn-code} class List[+T] #co(){ --------------- end-code} 型 #co(){ --------------- bgn-code} List[T] forSome { type T <: java.lang.Number } #co(){ --------------- end-code} は、上記の簡略化規則の 4 番目により、次と等価です。 #co(){ --------------- bgn-code} List[java.lang.Number] forSome { type T <: java.lang.Number } #co(){ --------------- end-code} #co(){----------------------------------------------------- bgn-hide0} which is in turn equivalent (by simplification rules 2 and 3 above) to List[java.lang.Number]. #co(){----------------------------------------------------- end-hide0} これは今度は(上記の簡略化規則 2 と 3 により)、List[java.lang.Number] と等価になります。 #center(){[[前:2章>Spec2.8Chap2a]]  [[目次>Spec2.8和訳]] [[次:3章つづき>Spec2.8Chap3b]]}
#setmenu2(spec2.8-r-menu) * 第 3 章 型 (Types) &bold(){構文:} Type ::= FunctionArgTypes '=>' Type | InfixType [ExistentialClause] FunctionArgTypes ::= InfixType | '(' [ ParamType {',' ParamType } ] ')' ExistentialClause ::= 'forSome' '{' ExistentialDcl {semi ExistentialDcl} '}' ExistentialDcl ::= 'type' TypeDcl | 'val' ValDcl InfixType ::= CompoundType {id [nl] CompoundType} CompoundType ::= AnnotType {'with' AnnotType} [Refinement] | Refinement AnnotType ::= SimpleType {Annotation} SimpleType ::= SimpleType TypeArgs | SimpleType '#' id | StableId | Path '.' 'type' | '(' Types ')' TypeArgs ::= '[' Types ']' Types ::= Type {',' Type} We distinguish between first-order types and type constructors, which take type parameters and yield types. A subset of first-order types called value types represents sets of (first-class) values. Value types are either concrete or abstract. 一階型と、パラメータを指定して型を生み出す型コンストラクタとを区別します。 &strong(){値型(value types)}と呼ばれる一階型の部分集合は、 (first class:第一級の)値の集合を表します。 値型は&strong(){具象あるいは抽象}のいずれかです。 Every concrete value type can be represented as a class type, i.e. a type designator (§3.2.3) that refers to a a class or a trait(*1)(§5.3), or as a compound type (§3.2.7) representing an intersection of types, possibly with a refinement (§3.2.7) that further constrains the types of its members. Abstract value types are introduced by type parameters (§4.4) and abstract type bindings (§4.3). Parentheses in types can be used for grouping. すべての具象値型は、&strong(){クラス型}として表せます。すなわち、 クラスやトレイト(*1)(&link_anchor(5.3,page=Spec2.8Chap5c2){§5.3}) を参照する型指定子 (&link_anchor(3.2.3,page=Spec2.8Chap3a){§3.2.3})、 あるいは、型の論理積(intersection)を表す&strong(){複合型} (&link_anchor(3.2.7,page=Spec2.8Chap3a){§3.2.7})としてです。 複合型には、そのメンバーの型にさらなる制約を与える細別 (refinement &link_anchor(3.2.7,page=Spec2.8Chap3a){§3.2.7}) を加えることができます。 抽象値型は、型パラメータ(&link_anchor(4.4,page=Spec2.8Chap4a){§4.4}) と抽象型束縛(&link_anchor(4.3,page=Spec2.8Chap4a){§4.3})によって導入されます。 型の中では、丸括弧をグルーピングのために使えます。 (*1) We assume that objects and packages also implicitly define a class (of the same name as the object or package, but inaccessible to user programs). (*1) 我々はオブジェクトとパッケージも暗黙のうちに (ユーザープログラムはアクセスできない、 オブジェクトあるいはパッケージと同じ名前の) クラスを定義すると考えます。 Non-value types capture properties of identifiers that are not values (§3.3). For example, a type constructor (§3.3.3) does not directly specify a type of values. However, when a type constructor is applied to the correct type arguments, it yields a first-order type, which may be a value type. 非値型は、値でない識別子のプロパティを取り込みます (&link_anchor(3.3,page=Spec2.8Chap3b){§3.3})。 例えば、型コンストラクタ (&link_anchor(3.3.3,page=Spec2.8Chap3b){§3.3.3}) は直接には値の型を指定しません。 しかし、型コンストラクタが正しい型引数に適用されれば、 それは値型であろう一階型をもたらします。 Non-value types are expressed indirectly in Scala. E.g., a method type is described by writing down a method signature, which in itself is not a real type, although it gives rise to a corresponding method type (§3.3.1). Type constructors are another example, as one can write type Swap[m[_, _], a,b] = m[b, a], but there is no syntax to write the corresponding anonymous type function directly. 非値型は Scalaでは間接的に表現されます。 例えば、 メソッド型はメソッドのシグニチャを書き出して記述できますが、 それ自身は実際の型でないけれども、 対応するメソッド型(&link_anchor(3.3.1,page=Spec2.8Chap3b){§3.3.1}) を引き起こします。 型コンストラクタは他の例です。型を Swap[m[_, _], a,b] = m[b, a] と書けますが、 しかし、対応する無名の型関数を直接的に書くための構文はありません。 &br() &br() &aname(3.1,option=nolink){ } ** 3.1 パス (Paths) &bold(){構文:} Path ::= StableId | [id '.'] this StableId ::= id | Path '.' id | [id '.'] 'super' [ClassQualifier] '.' id ClassQualifier ::= '[' id ']' Paths are not types themselves, but they can be a part of named types and in that function form a central role in Scala's type system. パスそれ自身は型ではありません。しかしそれは、名前付きの型(named type) の一部であり、その機能は Scala 型システムの中で中心的役割を果たします。 A path is one of the following. - The empty path (which cannot be written explicitly in user programs). - C.this, where C references a class. The path this is taken as a shorthand for C.this ,where C is the name of the class directly enclosing the reference. パスは次のうちの1つです。 - 空のパス (ユーザープログラム中では、明示的には書けません)。 - C.this。ここで C はクラスを参照します。パス this は C.this の略記表現として解釈されます。ここで C は、参照を直接囲むクラスの名前です。 - p.x where p is a path and x is a stable member of p. Stable members are packages or members introduced by object definitions or by value definitions of non-volatile types (§3.6). - C.super.x or C.super[M].x where C references a class and x references a stable member of the super class or designated parent class M of C. The prefix super is taken as a shorthand for C.super where C is the name of the class directly enclosing the reference. - p.x。ここで p はパス、x は p の安定メンバー。 &strong(){安定メンバー(stable members)}とは、オブジェクト定義によってあるいは非 volatile 型の値定義によって導入されたメンバーあるいはパッケージのことです(&link_anchor(3.6,page=Spec2.8Chap3b){§3.6})。 - C.super.x あるいは C.super[M].x。 ここで C はクラスを参照し、x は、スーパークラスあるいは C の指定された親クラス M の、安定メンバーを参照します。 前置子 super は、C.super の略記表現として解釈されます。 ここで C は、参照を直接囲むクラスの名前です。 A stable identifier is a path which ends in an identifier. &strong(){安定識別子(stable identifier)}とは、最後が識別子で終わるパスです。 &br() &br() &aname(3.2,option=nolink){ } ** 3.2 値型 (Value Types) Every value in Scala has a type which is of one of the following forms. Scala のすべての値は、次のどれか 1 つの形をとる型を持っています。 &br() &br() &aname(3.2.1,option=nolink){ } *** 3.2.1 シングルトン型 (Singleton Types) &bold(){構文:} SimpleType ::= Path '.' type A singleton type is of the form p.type, where p is a path pointing to a value expected to conform (§6.1) to scala.AnyRef. The type denotes the set of values consisting of null and the value denoted by p . A stable type is either a singleton type or a type which is declared to be a subtype of trait scala.Singleton. シングルトン型は p.type の形の型であり、ここで p はパスで、 scala.AnyRefに適合する (&link_anchor(6.1,page=Spec2.8Chap6a){§6.1})ことが要請される値を指し示します。 この型は、null と p で示される値からなる集合を表します。 &strong(){安定型(stable type)}とは、シングルトン型あるいは、 トレイト scala.Singleton のサブ型 (subtype) であると宣言された型、 のいずれかです。 &br() &br() &aname(3.2.2,option=nolink){ } *** 3.2.2 型射影 (Type Projection) &bold(){構文:} SimpleType ::= SimpleType '#' id A type projection T#x references the type member named x of type T . 型射影 T#x は、型 T の x という名前の型メンバーを参照します。 &br() &br() &aname(3.2.3,option=nolink){ } *** 3.2.3 型指定子 (Type Designators) &bold(){構文:} SimpleType ::= StableId A type designator refers to a named value type. It can be simple or qualified. All such type designators are shorthands for type projections. 型指定子は、名前付きの値型を参照します。 それは単純名であるか、 あるいは限定修飾されます。 そのような型指定子はすべて、型射影の略記表現です。 Specifically, the unqualified type name t where t is bound in some class, object, or package C is taken as a shorthand for C.this.type#t . If t is not bound in a class, object, or package, then t is taken as a shorthand for ε.type#t . A qualified type designator has the form p.t where p is a path (§3.1) and t is a type name. Such a type designator is equivalent to the type projection p.type#t . 特に、限定修飾されていない型名 t は、C.this.type#t の略記表現として解釈されます。 ここで t はあるクラス、オブジェクト、 あるいはパッケージ C 内で束縛されているものとします。 もし t がクラス、オブジェクト、あるいはパッケージ内で束縛されていないなら、 t は ε.type#t の略記表現と解釈されます。 限定修飾された型指定子は、p.t の形をしています。 ここで p はパス(&link_anchor(3.1,page=Spec2.8Chap3a){§3.1})、t は型名です。 そのような型指定子は型射影 p.type#t に等価です。 &br() &bold(){Example 3.2.1} Some type designators and their expansions are listed below. We assume a local type parameter t , a value maintable with a type member Node and the standard class scala.Int, 次は、いくつかの型指定子とそれらの展開をリストしています。 ここで、ローカルな型パラメータ t、型メンバー Nodeを持つ値 maintable、 標準的なクラス scala.Int があると仮定します。 t ε.type#t Int scala.type#Int scala.Int scala.type#Int data.maintable.Node data.maintable.type#Node &br() &br() &aname(3.2.4,option=nolink){ } *** 3.2.4 パラメータ化された型 (Parameterized Types) &bold(){構文:} SimpleType ::= SimpleType TypeArgs TypeArgs ::= '[' Types ']' A parameterized type T[U1,...,Un] consists of a type designator T and type parameters U1,...,Un where n>=1. T must refer to a type constructor which takes n type parameters a1,...,an . Say the type parameters have lower bounds L1,...,Ln and upper bounds U1,...,Un . The parameterized type is well-formed if each actual type parameter conforms to its bounds, i.e. σLi <: Ti <: σUi where σ is the substitution [a1 := T1,...,an := Tn]. パラメータ化された型 T[U1,...,Un] は、型指定子 T と 型パラメータ U1,...,Un (n >= 1) から成ります。 T は、n 個の型パラメータ a1,...,an をとる型コンストラクタを参照していなければなりません。 例えば、型パラメータが下限境界 L1,...,Ln と上限境界 U1,...,Un を持っているとします。 もし、それぞれ実際の型パラメータがその&strong(){両境界に適合する}なら、 つまり σLi <: Ti <: σUi なら (ここで σは置換[a1 := T1,...,an := Tn])、 このパラメータ化された型は正しい形(well formed)です。 &br() &bold(){Example 3.2.2} 次のような部分的な型定義が与えられているとします。 class TreeMap[A <: Comparable[A], B] { ... } class List[A] { ... } class I extends Comparable[I] { ... } class F[M[_], X] { ... } class S[K <: String] { ... } class G[M[ Z <: I ], I] { ... } このとき、次のパラメータ化された型は正しい形です。 TreeMap[I, String] List[I] List[List[Boolean]] F[List, Int] G[S, String] &br() &bold(){Example 3.2.3} 例3.2.2の型定義が与えられているとき、次の型は不正な形(ill-formed)です。 TreeMap[I] // 不正: パラメータ数誤り。 TreeMap[List[I], Int] // 不正: 型パラメータが境界外。 F[Int, Boolean] // 不正: Int は型コンストラクタではない。 F[TreeMap, Int] // 不正: TreeMap は 2 つのパラメータをとるが、 // F は 1 パラメータのコンストラクタである。 G[S, Int] // 不正: S は、Stringに適合するパラメータを含み、 // G は、Intに適合するパラメータをもつ // 型コンストラクタが要請される。 &br() &br() &aname(3.2.5,option=nolink){ } *** 3.2.5 タプル型 &bold(){構文:} SimpleType ::= '(' Types ')' タプル型 (T1,...,Tn) は、クラス scala.Tuplen[T1,...,Tn] のエイリアスです。ここで n >= 2。 タプルクラスはケースクラスであり、セレクター _1, ..., _n を使ってそのフィールドにアクセスできます。 Their functionality is abstracted in a corresponding Product trait. The n-ary tuple class and product trait are defined at least as follows in the standard Scala library (they might also add other methods and implement other traits). それらの関数は、対応する Product トレイト内にまとめられています。 n 項タプルクラスと product トレイトは、標準的な Scala ライブラリにおいて、 少なくとも次のように定義されています (他のメソッドも加え、また、他のトレイトも実装しているかもしれません)。 case class Tuplen[+T1, ..., +Tn](_1: T1, ..., _n : Tn) extends Productn[T1, ..., Tn] {} trait Productn[+T1, +T2, +Tn] { override def arity = n def _1: T1 ... def _n :Tn } &br() &br() &aname(3.2.6,option=nolink){ } *** 3.2.6 アノテーション型 (Annotated Types) &bold(){構文:} AnnotType ::= SimpleType {Annotation} An annotated type T a1...an attaches annotations a1,...,an to the type T (§11). アノテーション型 T a1...an は、型 T にアノテーション a1,...,an を付加します (&link_anchor(11,page=Spec2.8Chap11a){§11})。 &br() &bold(){Example 3.2.4} 次の型は、文字列型に @suspendable@ アノテーションを付加します: String @suspendable &br() &br() &aname(3.2.7,option=nolink){ } *** 3.2.7 複合型 (Compound Types) (訳注:複合型については [[A Tour of Scala:Compound Types>http://www.scala-lang.org/node/110]] に簡単な説明があります) &bold(){構文:} CompoundType ::= AnnotType {'with' AnnotType} [Refinement] | Refinement Refinement ::= [nl] '{' RefineStat {semi RefineStat} '}' RefineStat ::= Dcl | 'type' TypeDef | A compound type T1 with ... with Tn {R } represents objects with members as given in the component types T1,...,Tn and the refinement {R }. A refinement {R} contains declarations and type definitions. If a declaration or definition overrides a declaration or definition in one of the component types T1,...,Tn , the usual rules for overriding (§5.1.4) apply; otherwise the declaration or definition is said to be "structural" (*2) . 複合型 T1 with ... with Tn {R} は、構成要素型 T1,...,Tn と細別 {R} で与えられたメンバーをもつオブジェクトを表わします。 細別 {R} は、宣言と型定義を含みます。 もし宣言あるいは定義が、構成要素型 T1,...Tn の 1 つの中の宣言あるいは定義をオーバライドするなら、 オーバライドの通常の規則が適用されます (&link_anchor(5.1.4,page=Spec2.8Chap5a){§5.1.4}); そうでないなら、宣言あるいは定義は「構造的」と言われます(*2)。 (*2) A reference to a structurally defined member (method call or access to a value or variable) may generate binary code that is significantly slower than an equivalent code to a non-structural member. (*2) 構造的に定義されたメンバーへの参照(メソッド呼び出しあるいは、 値/変数へのアクセス)は、非構造的メンバーを参照する等価なコードより、 際立って遅いバイナリコードを生成することがあります。 Within a method declaration in a structural refinement, the type of any value parameter may only refer to type parameters or abstract types that are contained inside the refinement. That is, it must refer either to a type parameter of the method itself, or to a type definition within the refinement. This restriction does not apply to the function's result type. 構造的な細別内のメソッド宣言では、すべての値パラメータの型は、その細別内に 含まれる型パラメータあるいは抽象型だけを参照できます。 すなわち、 メソッド自身の型パラメータへの参照であるか、あるいは、 細別内の型定義への参照のいずれかです。 この制限は関数の結果型には適用されません。 もし細別が与えられていなければ、空の細別が暗黙のうちに加えられます。 つまり、T1 with ... with Tn は、T1 with ... with Tn {} の略記表現です。 複合型は、先行する構成要素型のない、細別 {R} だけから成ることもあります。 そのような型は AnyRef {R} に等価です。 &br() &bold(){Example 3.2.5} 次の例は、関数のパラメータ型が構造的宣言をもつ細別を含む場合の、 宣言方法と使い方を示しています。 case class Bird (val name: String) extends Object { def fly(height: Int) = ... ... } case class Plane (val callsign: String) extends Object { def fly(height: Int) = ... ... } def takeoff( runway: Int, r: { val callsign: String; def fly(height: Int) }) = { tower.print(r.callsign + " requests take-off on runway " + runway) tower.read(r.callsign + " is clear for take-off") r.fly(1000) } val bird = new Bird("Polly the parrot"){ val callsign = name } val a380 = new Plane("TZ-987") takeoff(42, bird) takeoff(89, a380) Although Bird and Plane do not share any parent class other than Object, the parameter r of function takeoff is defined using a refinement with structural declarations to accept any object that declares a value callsign and a fly function. Bird と Plane は Object 以外の親クラスを共有していませんが、 関数 takeoff のパラメータ r は、構造的宣言の細別を使って定義されていて、 値 callsign と fly 関数を宣言する任意のオブジェクトを受けつけます。 &br() &br() &aname(3.2.8,option=nolink){ } *** 3.2.8 中置型 (Infix Types) &bold(){構文:} InfixType ::= CompoundType {id [nl] CompoundType} An infix type T1 op T2 consists of an infix operator op which gets applied to two type operands T1 and T2 . The type is equivalent to the type application op[T1 , T2]. 中置型 T1 op T2 は、2 つのオペランド型 T1 と T2 へ適用される中置演算子 op からなります。 この型は型適用 op[T1,T2] に等価です。 中置演算子 op には、* 以外の任意の識別子が使えます。 * は 反復パラメータ型(&link_anchor(4.6.2,page=Spec2.8Chap4b){§4.6.2}) を表す後置修飾子として予約されています。 All type infix operators have the same precedence; parentheses have to be used for grouping. The associativity (§6.12) of a type operator is determined as for term operators : type operators ending in a colon ':' are right-associative; all other operators are left-associative. すべての中置型演算子は同じ優先順位を持っています; グルーピングには丸括弧を使われなければなりません。 型演算子の結合性(&link_anchor(6.12,page=Spec2.8Chap6b){§6.12})は 項演算子(term operator)については決まっています。 ':'で終わる型演算子は右結合です。他のすべての演算子は左結合です。 In a sequence of consecutive type infix operations t0 op1 t1 op2 ... opn tn , all operators op1,...,opn must have the same associativity. If they are all left-associative, the sequence is interpreted as (... (t0 op1 t1 ) op2 ...) opn tn , otherwise it is interpreted as t0 op1 (t1 op2 (... opn tn ) ...). 連続する中置型演算のシーケンス t0 op1 t1 op2 ... opn tn では、 すべての演算子 op1,...,opn が同じ結合性を持っていなくてはなりません。 もしそれらがすべて左結合なら、シーケンスは (... (t0 op1 t1 ) op2 ...) opn tn と解釈され、そうでなければ t0 op1 (t1 op2 (... opn tn ) ...) と解釈されます。 &br() &br() &aname(3.2.9,option=nolink){ } *** 3.2.9 関数型 (Function Types) &bold(){構文:} Type ::= FunctionArgs '=>' Type FunctionArgs ::= InfixType | '(' [ ParamType {',' ParamType } ] ')' The type (T1,...,Tn ) => U represents the set of function values that take arguments of types T1,...,Tn and yield results of type U . In the case of exactly one argument type T => U is a shorthand for (T ) => U . An argument type of the form => T represents a call-by-name parameter (§4.6.1) of type T . 型 (T1,...,Tn) => U は、型 T1,...,Tn を引数にとり、型 U の結果をもたらす関数値の集合を表します。引数が正確に 1 つだけの場合は、 型 T => U は (T) => U の略記表現です。 形が => T の引数型は、型 T の名前呼出しパラメータ (&link_anchor(4.6.1,page=Spec2.8Chap4b){§4.6.1})を表します。 Function types associate to the right, e.g. S => T => U is the same as S => (T => U ). Function types are shorthands for class types that define apply functions. Specifically , the n-ary function type (T1,...,Tn ) => U is a shorthand for the class type Functionn[T1,...,Tn ,U]. Such class types are defined in the Scala library for n between 0 and 9 as follows. 関数型は右へ結合します。例えば、S => T => U は S => (T => U) と同じです。 関数型は、apply 関数を定義するクラス型の略記表現です。 特に、n 項関数型 (T1,...,Tn) => U は、クラス型 Functionn[T1,...,Tn,U] の略記表現です。 このようなクラス型は、0 以上 9 以下の n に対して Scala ライブラリ中で、次のように定義されています。 package scala trait Functionn[-T1,...,-Tn , +R] { def apply(x1 : T1,...,xn : Tn ): R override def toString = "<function>" } Hence, function types are covariant (§4.5) in their result type and contravariant in their argument types. したがって、関数型は、その結果型については共変 (&link_anchor(4.5,page=Spec2.8Chap4a){§4.5})、その引数型については反変です。 &br() &br() &aname(3.2.10,option=nolink){ } *** 3.2.10 存在型 (Existential Types) &bold(){構文:} Type ::= InfixType ExistentialClauses ExistentialClauses ::= 'forSome' '{' ExistentialDcl {semi ExistentialDcl} '}' ExistentialDcl ::= 'type' TypeDcl | 'val' ValDcl An existential type has the form T forSome { Q } ,where Q is a sequence of type declarations §4.3. Let t1[tps1] >: L1 <: U1,...,tn[tpsn] >: Ln <: Un be the types declared in Q (any of the type parameter sections [tpsi] might be missing). The scope of each type ti includes the type T and the existential clause Q. The type variables ti are said to be bound in the type T forSome { Q }. Type variables which occur in a type T but which are not bound in T are said to be free in T . 存在型は、T forSome { Q } の形をしています。ここで Q は型宣言 (&link_anchor(4.3,page=Spec2.8Chap4a){§4.3})の並びです。 t1[tps1] >: L1 <: U1,...,tn[tpsn] >: Ln <: Un を Q 内で宣言された型であるとします (型パラメータ部 [tpsi] のどれかが欠けていても構いません)。 各型 ti のスコープは、型 T と存在節 Q を含みます。 型変数 ti は、型 T forSome { Q } 内で&strong(){束縛}されていると言われます。 型 T の中に現れるけれど T 内で束縛されない型変数は、 T 内で&strong(){自由(free)}であると言われます。 A type instance of T forSome { Q } is a type σT , where σ is a substitution over t1,...,tn such that, for each i , σLi <: σti <: σUi . The set of values denoted by the existential type T forSome { Q } is the union of the set of values of all its type instances . T forSome { Q }の&strong(){型インスタンス}は、型 σT です。 ここで σは、各 i に対し σLi <: σti <: σUi であるような t1,...,tn の置換とします。 存在型 T forSome { Q } によって示される値の集合は、 そのすべての型インスタンスの値の集合の和集合です。 A skolemization of T forSome { Q } is a type instance σT , where σ is the substitution [t´1/t1,...,t´n/tn] and each t´i is a fresh abstract type with lower bound σLi and upper bound σUi . T forSome { Q } の skolemization は、型インスタンス σT です。ここで σは、 [t´1/t1,...,t´n/tn] の置換で、各 t´i は、下限境界 σLi と上限境界 σUi をもつ新規の抽象型です。 &br() &bold(){簡略化規則} 存在型は、次の 4 つの等価規則に従います。 + Multiple for clauses in an existential type can be merged. E.g., T forSome { Q } forSome { Q´} is equivalent to T forSome { Q ; Q´}. + Unused quantifications can be dropped. E.g., T forSome { Q ; Q´} where none of the types defined in Q´ are referred to by T or Q, is equivalent to T forSome { Q }. + An empty quantification can be dropped. E.g., T forSome { } is equivalent to T . + An existential type T forSome { Q } ,where Q contains a clause type t[tps] >: L <: U is equivalent to the type T´ forSome { Q } ,where T´ results from T by replacing every covariant occurrence (§4.5) of t in T by U and by replacing every contravariant occurrence of t in T by L. + 存在型中の複数の for 節をマージできます。例えば、T forSome { Q } forSome { Q´} は T forSome { Q ; Q´} に等価です。 + 使われていない存在量化(quantification)を外すことができます。例えば、T forSome { Q ; Q´} は、T forSome { Q } に等価です。ただしここで Q´中で 定義されたどの型も、T あるいは Q によって参照されないものとします。 + 空の存在量化を外すことができます。例えば、T forSome { } は T に等価です。 + 存在型 T forSome { Q } (ここで Q は節 type t[tps] >: L <: U を含む) は、型 T´ forSome { Q } に等価です。ここで T´は、T 中で共変(&link_anchor(4.5,page=Spec2.8Chap4a){§4.5})として出現するすべての t を U で置き換え、T 中で反変として出現するすべての t を L で置き換えて得られるものです。 &br() &bold(){値の存在量化 (Existential Quantification over Values)} As a syntactic convenience, the bindings clause in an existential type may also contain value declarations val x : T . An existential type T forSome { Q ; val x : S ; Q´ } is treated as a shorthand for the type T´ forSome { Q ; type t <: S with Singleton; Q´ }, where t is a fresh type name and T´ results from T by replacing every occurrence of x.type with t . 文法上の便宜として、存在型中の束縛節に値宣言 val x : T を含めることができます。 存在型 T forSome { Q; val x : S ; Q´ } は、 型 T´ forSome { Q ; type t <: S with Singleton; Q´ } の略記表現として扱われます。ここで t は新たな型名で、 T´ は T 中に現れる x.type を t で置き換えて得られるものです。 &br() &bold(){存在型のプレースホルダ構文} &bold(){構文:} WildcardType ::= '_' TypeBounds Scala supports a placeholder syntax for existential types. A wildcard type is of the form _ >: L <: U . Both bound clauses may be omitted. If a lower bound clause >: L is missing, >: scala.Nothing is assumed. If an upper bound clause <: U is missing , <: scala.Any is assumed. A wildcard type is a shorthand for an existentially quantified type variable, where the existential quantification is implicit. Scala は存在型のプレースホルダ構文をサポートしています。 &strong(){ワイルドカード型}は _ >: L <: U の形です。 それぞれの境界節はともに省略されるかもしれません。 もし下限境界節 >: L がないなら、>: scala.Nothing が想定されます。 もし上限境界節 <: U がないなら、<: scala.Any が想定されます。 ワイルドカード型は存在量化された型変数の略記表現です。 ここで、存在量化は暗黙的です。 A wildcard type must appear as type argument of a parameterized type. Let T = p.c[targs,T,targs´] be a parameterized type ,where targs,targs´ may be empty and T is a wildcard type _ >: L <: U . Then T is equivalent to the existential type ワイルドカード型は、パラメータ化された型の型引数として現われなくてはなりません。 いま、T = p.c[targs,T,targs´] をパラメータ化された型とします。 ここで targs,targs´ は空きでもよく、T はワイルドカード型 _ >: L <: U です。 このとき T は、次の存在型 p.c[targs,t,targs´] forSome { type t >: L <: U } where t is some fresh type variable. Wildcard types may also appear as parts of infix types (§3.2.8), function types (§3.2.9), or tuple types (§3.2.5). Their expansion is then the expansion in the equivalent parameterized type. と等価になります。ここで t は、ある新しい型変数とします。 ワイルドカード型は、 中置型(&link_anchor(3.2.8,page=Spec2.8Chap3a){§3.2.8})、 関数型(&link_anchor(3.2.9,page=Spec2.8Chap3a{§3.2.9})、 あるいはタプル型(&link_anchor(3.2.5,page=Spec2.8Chap3a){§3.2.5}) 等の一部にも現れることがあります。 それらの展開は、等価なパラメータ化された型内での展開となります。 &br() &bold(){Example 3.2.6} 次のクラス定義を仮定します。 class Ref[T] abstract class Outer { type T } 次は、存在型のいくつかの例です。 Ref[T] forSome { type T <: java.lang.Number } Ref[x.T] forSome { val x: Outer } Ref[x_type# T] forSome { type x_type <: Outer with Singleton } 上記リストの最後の 2 つの型は等価です。 最初の型をワイルドカード構文を使って書き換えると次のようになります。 Ref[_ <: java.lang.Number] &br() &bold(){Example 3.2.7} 型 List[List[_]] は、次の存在型に等価です。 List[List[t] forSome { type t }] &br() &bold(){Example 3.2.8} 次の共変型があるとします。 class List[+T] 型 List[T] forSome { type T <: java.lang.Number } は、上記の簡略化規則の 4 番目により、次と等価です。 List[java.lang.Number] forSome { type T <: java.lang.Number } which is in turn equivalent (by simplification rules 2 and 3 above) to List[java.lang.Number]. これは今度は(上記の簡略化規則 2 と 3 により)、List[java.lang.Number] と等価になります。 #center(){[[前:2章>Spec2.8Chap2a]]  [[目次>Spec2.8和訳]] [[次:3章つづき>Spec2.8Chap3b]]}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。