ST 計算で複数の STUArray を作成して使用する方法を研究してきました。具体的なシナリオは次のとおりです。
- 複数の配列を作成しますが、そのうちの 1 つだけを返します
- 複数の配列を作成しますが、それらのいずれも返しません
- 複数の配列を作成し、複数の配列を返す
(1)と(2)には答えがありますが、(3)にはありません。
最初にいくつかのインポートを行って、すべてがどこから来ているかを確認します。
import Control.Monad.ST (ST,runST)
import Data.Array.Base (unsafeFreezeSTUArray)
import Data.Array.ST (STUArray)
import Data.Array.Unboxed (UArray)
import Data.STRef (STRef, newSTRef, readSTRef, writeSTRef)
import Data.Array.MArray (getBounds, newArray, readArray, writeArray, newListArray)
import Data.Array.ST (runSTUArray)
(1) の場合、1 つのトリックは、新しいデータ型とコンストラクター関数を定義することです。
data ArrayPair s = AP (STUArray s Int Int) (STUArray s Int Bool)
newAP n = do
a1 <- newArray (1,n) 0
a2 <- newArray (1,n) False
return $ AP a1 a2
配列の 1 つだけを返す方法は次のとおりです。
foo :: UArray Int Int
foo = runSTUArray $ do
AP ints bools <- newAP 10
writeArray ints 1 42
writeArray bools 1 True
-- do stuff with ints and bools
return ints
STRef
(2) の場合、データ構造に を追加し、 で計算を終了し、readSTRef
で実行できますrunST
。
data WorkState s = WS (STUArray s Int Int)
(STUArray s Int Bool)
(STRef s Char)
newWS = do
ints <- newArray (1,10) 0
bools <- newArray (1,20) False
char <- newSTRef 'X'
return $ WS ints bools char
bar :: Char
bar = runST $ do
WS ints bools char <- newWS
writeArray ints 3 36
writeArray bools 5 True
writeSTRef char 'Z'
-- ...
readSTRef char
ケース (1) および (2) に対するこのアプローチについてのコメントはありますか? では(3)の場合はどうでしょうか。
baz :: (UArray Int Int, UArray Int Bool)
baz = runST??? $ do
AP ints bools <- newAP
...
return (ints,bools) -- ???