简体   繁体   English

使用并返回多个STUArray

[英]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: 具体方案是:

  1. create multiple arrays but return only one of them 创建多个数组,但仅返回其中一个
  2. create multiple arrays but return none of them 创建多个数组,但都不返回
  3. create multiple arrays and return multiple arrays 创建多个数组并返回多个数组

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个选择:

  1. 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) 
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM