2016-04-06 6 views
2

scalaの値を使用して型をパラメータ化する方法はありますか?あなたは[5,1]で[2,3]行列を掛けることができないので、例えば、何かのようなので、それのサイズで行列をパラメータする...Scalaのサイズパラメータ化

val m1 = new Matrix[2,3]() 
val m2 = new Matrix[5,1]() 

val m3 = m1 multiply m2 

は例外をスローしますか?

これは、タプルやベクトルなどの他のタイプを実装する場合にも役立ちます。誰もこれを達成する方法を知っていますか?我々は、すべてのは、彼らがNatのすべてのサブタイプですが、_1_2は別個のタイプなので、彼らは分散せず、互いの代わりに使用することはできませんここでは0から始まる自然数であるタイプを定義することができペアノ番号を使用して

+1

これは従属型と呼ばれ、Scalaにはそれがありません。 [Shapeless](https://stackoverflow.com/questions/28287612/how-to-require-typesafe-constant-size-array-in-scala)は途中であなたを得ることができます。 –

+0

この場合、依存する必要はありません(タイピング)。 Peano番号を使用して型の階層を定義することができます。また、コードがコンパイルされている限り、それ以外の場合は継承されません。 –

答えて

4

自然数を定義します。

scala> sealed trait Nat 
defined trait Nat 

scala> sealed trait _0 extends Nat 
defined trait _0 

scala> sealed trait Succ[N <: Nat] extends Nat 
defined trait Succ 

scala> type _1 = Succ[_0] 
defined type alias _1 

scala> type _2 = Succ[_1] 
defined type alias _2 

マトリックスは、そのパラメータの型に不変である:

scala> case class Matrix[A <: Nat, B <: Nat](ignoreThis: String) 
defined class Matrix 

乗算機能も不変である:

scala> def multiply[R1 <: Nat, C1 <: Nat, C2 <: Nat](m1: Matrix[R1, C1], m2: Matrix[C1, C2]) = Matrix[R1, C2](m1.ignoreThis + m2.ignoreThis) 
multiply: [R1 <: Nat, C1 <: Nat, C2 <: Nat](m1: Matrix[R1,C1], m2: Matrix[C1,C2])Matrix[R1,C2] 

コンパイラは、チェックを行いますあなたのために、寸法は一致します:

scala> multiply(Matrix[_1, _2]("one"), Matrix[_2, _1]("two")) 
res0: Matrix[_1,_1] = Matrix(onetwo) 

寸法は、一致時エラーが実行時よりもはるかに優れてコンパイルされません。

scala> multiply(Matrix[_1, _2]("one"), Matrix[_1, _1]("two")) 
<console>:19: error: type mismatch; 
found : Matrix[_1(in object $iw),_2] 
    (which expands to) Matrix[Succ[_0],Succ[Succ[_0]]] 
required: Matrix[_1(in object $iw),Succ[_ >: _0 with _1(in object $iw) <: Nat]] 
    (which expands to) Matrix[Succ[_0],Succ[_ >: _0 with Succ[_0] <: Nat]] 
Note: _2 <: Succ[_ >: _0 with _1 <: Nat], but class Matrix is invariant in type B. 
You may wish to define B as +B instead. (SLS 4.5) 
     multiply(Matrix[_1, _2]("one"), Matrix[_1, _1]("two")) 
          ^
<console>:19: error: type mismatch; 
found : Matrix[_1(in object $iw),_1(in object $iw)] 
    (which expands to) Matrix[Succ[_0],Succ[_0]] 
required: Matrix[Succ[_ >: _0 with _1(in object $iw) <: Nat],_1(in object $iw)] 
    (which expands to) Matrix[Succ[_ >: _0 with Succ[_0] <: Nat],Succ[_0]] 
Note: _1 <: Succ[_ >: _0 with _1 <: Nat], but class Matrix is invariant in type A. 
You may wish to define A as +A instead. (SLS 4.5) 
     multiply(Matrix[_1, _2]("one"), Matrix[_1, _1]("two")) 
                ^

私はそれゆえignoreThisプレースホルダを実際の乗算の実装を書くのが面倒でした。

+0

すごい!任意のライブラリを使用していますか? –

+0

これは純粋なScalaであり、特別なライブラリはありません。型安全な数学構造や演算をより適切かつ完全に実装する必要があると確信しています。 –

+0

これはScalaがこれを行うために必要な歪みをどのようにサポートしているかを示していますが、これらのエラーメッセージは不透明です。そしてMatrix [_100、_256]や何かをするために必要な定型文は膨大なものになるでしょう。 –

関連する問題