2016-12-19 4 views
1

静的なボクセルシーンをレンダリングし、途中でHaskellを学習するための最適化手法をいくつか試しています。私はOOPのクラス特化に相当するHaskell

VoxelIdは、単に Intの別名である
type Voxel = (VoxelId, Position). 

として定義されたボクセルを持っています。私はラインの下で線形代数を予想しているので、Positionは3次元ベクトルを表現したいと思っていました。私が使用しているライブラリ(matrix)はMatrixのデータ型しか実装していませんが、ポジションの基底型がMatrixの場合、それ以上の計算が単純化されます。

しかし、Positionは3次元のベクトルよりも何か他のものであるために、それはあまり意味がありませんので、私は3×1行列にPositionを制限したいと思いますので、私は、関数のシグネチャで特異的にPosition使用するときに、私は」 3x1の行列またはコンパイルエラーのいずれかが予想されます。

class Matrix 
{ 
    Matrix(int rows, int columns) 
    {} 
} 

class Position : public Matrix 
{ 
    Position() 
    : Matrix (3, 1) 
    {} 
} 

と私は3×1行列と参照のみが他のどこでも行列に予想される場合Positionを使用:C++または私はこのような何かを行うことができ、他のオブジェクト指向言語で

はのは、私はどのように私はPositionのためにすべての操作Matrix実装を再定義することなく、Haskellで、この動作を複製することができます

matrix :: (rows) -> (columns) -> Matrix 

コンストラクタ関数を持って使用していますライブラリからMatrixを想定してみましょうか?

+1

ハスケルでは不変ですが空のベクトルを構成するのは意味がありません。あなたができることは、あなた自身の "スマートなコンストラクタ"(基本的な機能)を定義することです。 '(Double、Double、Double)'を返し、行列を返します。より静的な保証が必要な場合は、結果の行列を 'newtype'ラッパーに入れます(ラッパー上のすべての行列演算を定義するか、毎回ラップ解除する必要があります)。 – chi

+0

Positionのマトリックス操作を再定義することは、第三者のライブラリを使用する目的を破ります。最後の手段として残しておきたいことです。元の質問を編集してより明確にしました。 –

+0

次に、毎回手動でアンラップするか、安全な変換を使用する必要があります。または、次のようにダンベルコンストラクタを使用します。 – chi

答えて

1

ハスケルでは、OOPのようなサブタイプはありません。

あなたは、データ型

newtype Position = P { unP :: Matrix ... } 
    deriving (Show) -- , etc. 

とあなたが本当に内部表現を隠したい場合は、独自のモジュールおよびエクスポートに上記を置くことができる

position :: Double -> Double -> Double -> Position 
position x1 x2 x3 = 
    Position (newMatrix 1 3 [[x1,x2,x3]]) -- pseudo code 

スマートコンストラクタを所有して定義することができますスマートコンストラクタのみ。ただし、これを実行すると、必要なすべての操作を定義してエクスポートする必要があります。そうでないと便利ではありません。

表現を非表示にしないと仮定すると、PositionMatrix ...は2つの異なるタイプであることに注意してください。だからPositionMatrixとしたいものに渡すことはできません。だから、代わりの

matrixMultiply somePosition someMatrix 

1は

matrixMultiply (unP somePosition) someMatrix 

を行い、Matrix結果を取得する必要があります。結果ではなくPositionする必要がある場合、1缶/カスタム乗算関数を定義する必要があります:

posMultiply :: Position -> Matrix ... -> Position 
posMultiply m _ | wrongSize m = error "matrix has the wrong size!" 
posMultiply m (Position p) = Position (matrixMultiply m p) 

したい保証どのくらい静的に応じて、これは少し面倒かもしれません。 多くの場合、safe coercionsは痛みを和らげることができます。

もっと簡単な方法は、カスタムタイプを使用しないダンベルコンストラクタを使用することです。これは単なる関数です

position :: Double -> Double -> Double -> Matrix ... 
position x1 x2 x3 = 
    newMatrix 1 3 [[x1,x2,x3]] -- pseudo code 
+0

答えをありがとう、私は、私はこれらのソリューションのいずれかの巨大なファンではないことを認めなければならないが、私はこの問題をどう扱うか考えていると思う。 私は、Haskellの型システムのトレードオフについて、Simon Peytonの話を覚えています。「Haskellでは、既存の型に新しい機能を追加するのは簡単ですが、命令型言語では新しい既存の機能を入力してください。どちらの場合も、inverseは本当に乱雑です」と、私はこれがこのステートメントが真実であることを示すケースであると考えます。 –

+0

@ReverentLapwingはい、私は同意します。これは「表現の問題」(https://en.wikipedia.org/wiki/Expression_problem)として知られています。 – chi

関連する問題