2013-01-13 8 views
5

IOArray、またはMArrayのうち一般にスライス(サブアレイビュー)を効率的に構築する方法はありますか?つまり、同じ配列をとって、境界を制限するだけです。署名は、境界(1,1000)だけ元の配列の境界(500,700)持つ要素へのアクセスを与える表示を行うと、配列をとる、例えば一般的にIOArray(またはMArray)をスライスする

(MArray a e m, Ix i) => a i e -> i -> i -> m (a i e) 

とすることができます。ドキュメントを検索しましたが、そのような機能は見つかりませんでした。

+0

したがって、 '[500..700]' _remapped_を '[0..200]'にするか、何らかの方法でアクセスする必要があります(例えば、外部にアクセスするときに 'IO'例外を投げる範囲)? '[(20,20)..(40,40)]'のような範囲の多次元配列に対しては、どのように振る舞いますか? – leftaroundabout

+4

そうは思いませんが、Data.Vector http://hackage.haskell.org/package/vector-0.10.0.1を使用すると、スライスを抽出できます。融合最適化ルールもありますので、一般的にはより効率的です。 –

+0

@leftaroundabout再マッピングは必要ありません。基本的に私が望むのは、 'getBounds'が制限された範囲を報告する同じ配列を持つことです(おそらく、外部の要素にアクセスすると例外がスローされますが、これは必須ではありません)。 –

答えて

5

配列の型がどのように実装されているかを考えれば、実際に配列の特徴となるものではありません。

配列は連続したメモリブロックであることを思い出してください。あるレベルでは、n要素を持つ配列はすべて(0, n-1)です。しかし、整数以外のインデックスをゼロから始めることが一般的であるため、Haskellは任意の境界を定義し、その境界内の要素から実際のメモリブロックの0ベースの整数インデックスに変換するためにa type classを提供しています。

これは、配列の境界がその範囲全体をカバーしていると想定されているため、やりたいことをいくらか困難にします。したがって、同じメモリチャンクを使用する既存の配列のコピーを作成し、境界が異なる場合は、インデックスが整列しません - 例では、サブアレイのインデックス500は元のインデックス1と同じになりますアレイ。役に立たない。

ここで最も簡単なアプローチは、既存の配列をラップし、インデックスを変換するために必要な追加情報を格納する独自の配列型を定義することで、独自の境界をより小さな範囲としてレポートしますが、全範囲に基づく配列。次に、 "実際の"配列と同じ境界を使用するだけで、新しく作成された配列でラップされた配列型をどこでも使用できます(期待されるすべてのインスタンスに& c)。ここでインデックスに必要な変換を実行できます。このアプローチは、線形の順序も持たない型(たとえば、タプルでインデックスされた「多次元」配列)を一般化する必要があります。

インデックスタイプのラッパーを使用し、ラッパーバージョンに奇妙なIxインスタンスを与えることで、何かを自動的に処理して、既存の配列タイプを使用できるようにすることもできます。しかし、それはおそらく、正しく動作させるのが難しいでしょう。

配列型やインデックス型を変更せずに行う方法はないと思います。

関連する問題