2

ST 計算で複数の STUArray を作成して使用する方法を研究してきました。具体的なシナリオは次のとおりです。

  1. 複数の配列を作成しますが、そのうちの 1 つだけを返します
  2. 複数の配列を作成しますが、それらのいずれも返しません
  3. 複数の配列を作成し、複数の配列を返す

(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)  -- ???
4

1 に答える 1