[英]using and returning multiple STUArrays
I've been working out how to create and use multiple STUArrays in an ST computation. 我一直在研究如何在ST计算中创建和使用多个STUArray。 The specific scenarios are:
具体方案是:
I have answers to (1) and (2), but not (3). 我有(1)和(2)的答案,但没有(3)的答案。
First some imports so we know where everything is coming from: 首先是一些进口,所以我们知道一切都来自哪里:
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)
For (1), one trick is to define a new data type and constructor function: 对于(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
And here's how to return just one of the arrays: 以下是仅返回数组之一的方法:
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
For (2), you can add an STRef
to the data structure, end the computation with a readSTRef
and run it with runST
: 对于(2),你可以添加一个
STRef
的数据结构,结束与计算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
Comments on this approach for cases (1) and (2)? 对于情况(1)和(2),对此方法有何评论? And what about case (3)?
那么情况(3)呢?
baz :: (UArray Int Int, UArray Int Bool)
baz = runST??? $ do
AP ints bools <- newAP
...
return (ints,bools) -- ???
You have 2 options: 您有2个选择:
Use freeze
. 使用
freeze
。 This requires copying arrays, but you don't need to use any unsafe functions: 这需要复制数组,但是您不需要使用任何不安全的函数:
baz :: (UArray Int Int, UArray Int Bool) baz = runST $ do AP ints bools <- newAP 12 liftM2 (,) (freeze ints) (freeze bools)
Create your variant of runSTUArray
for two arrays using unsafeFreezeSTUArray
, knowing that the implementation is actually safe (because there will be no reference to the original mutable arrays left). 创建您的变种
runSTUArray
使用两个数组unsafeFreezeSTUArray
,明知实现实际上是安全的(因为将有原来的可变阵列左侧没有提及)。
runSTUArray2 :: (Ix i1, Ix i2) => (forall s . (ST s (STUArray s i1 e1, STUArray s i2 e2))) -> (UArray i1 e1, UArray i2 e2) runSTUArray2 st = runST $ do (a1, a2) <- st liftM2 (,) (unsafeFreezeSTUArray a1) (unsafeFreezeSTUArray a2) baz' :: (UArray Int Int, UArray Int Bool) baz' = runSTUArray2 $ do AP ints bools <- newAP 12 return (ints, bools)
(Perhaps this approach could be even somehow generalized using Generics to allow to return any data structure containing ST
arrays.) (也许这种方法甚至可以使用泛型以某种方式推广,以允许返回任何包含
ST
数组的数据结构。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.