Anon
Anon

Reputation: 385

How to make a local counter within another stateful action

   func :: Double -> Array U Ix1 Bool
   func x = runST (do y <- makeMArray' (Sz1 10)
                      loopM_ 0 (<10) (+1) (\s -> writeM y (index) (realtoFrac (s) > x))
                      unsafeFreeze Par y)

So i have this function where for efficiency reasons within an array structure from the massiv package i have to use loops to generate permutations and combinations of values used in the Bool expression (realtoFrac (s) > x ) then sequentially write each unique Bool to an element of the array y. In reality there are several nested loops with various increments and ranges so the Bool Expression would look like :: x -> s -> s1 -> s2 .. -> Bool. So i cant use a function that predicts what the index will be for a given set of loop counters within the nested loop not only because its somewhat difficult to formulate but also for generality when creating variations of this function f with different nested loop increments and ranges. So i have to use some type of counter that updates (+1) every time the inner most loop in the nest writes to y incrementing the (index).

I haven't had much experience with State monads or Supply monads but i'm guessing that's what needs to be used for this. Can anyone help me figure out how to address this please?

Upvotes: 1

Views: 50

Answers (1)

Noughtmare
Noughtmare

Reputation: 10645

You can use an STRef:

import Data.STRef

func :: Double -> Array U Ix1 Bool
func x = runST $ do
  y <- makeMArray' (Sz1 10)
  indexRef <- newSTRef 0
  loopM_ 0 (<10) (+1) $ \s -> do
    index <- readSTRef indexRef
    writeM y index (realtoFrac s > x)
    writeSTRef indexRef (index + 1)
  unsafeFreeze Par y

Upvotes: 2

Related Questions