簡単に言えば、あなたが望むものを許可するシステムがあります。たとえばST
、Haskell のモナドを使用してそれを行うことができます (コメントで参照されているように)。
モナドのST
アプローチは Haskell のものControl.Monad.ST
です。ST
モナドで書かれたコードはSTRef
、便利な場所で参照 ( ) を使用できます。ST
良い点は、本質的に自己完結型である ため、モナドの結果を純粋なコードで使用することもできることです(これは基本的に、質問で求めていたものです)。
この自己完結型のプロパティの証明は、型システムを通じて行われます。モナドはST
、通常 type-variable で示される state-thread パラメータを運びますs
。このような計算を行うと、次のような型のモナド結果が得られます。
foo :: ST s Int
これを実際に純粋な結果にするには、使用する必要があります
runST :: (forall s . ST s a) -> a
この型は次のように読むことができます:s
型パラメーターが重要でない計算をしてくださいST
。バゲージなしで、計算の結果を返すことができます。これは基本的に、可変変数が型システムによってキャッチされる をST
運ぶため、可変変数がエスケープするのを防ぎます。s
これは、基礎となる変更可能な構造 ( vector パッケージなど) で実装されている純粋な構造に対して効果的に使用できます。基になる配列をその場で変更する何かを行うために、限られた時間だけ不変性を捨てることができます。たとえば、イミュータブルVector
を不純なアルゴリズム パッケージと組み合わせて、インプレース ソート アルゴリズムのパフォーマンス特性を最大限に維持しながら、純度を維持することができます。
この場合、次のようになります。
pureSort :: Ord a => Vector a -> Vector a
pureSort vector = runST $ do
mutableVector <- thaw vector
sort mutableVector
freeze mutableVector
および関数は線形時間のコピーですが、これにより全体的な O(n lg n) の実行時間が中断されることはありませんthaw
。可変ベクトルが再び使用されないため、別の線形トラバーサルを回避するためにfreeze
使用することもできます。unsafeFreeze