1

So I want to create a method that works the same way as

import Data.Vector as V
import Data.Vector.Mutable as MV
import Control.Monad.ST

type DoubleVec = V.Vector Double

incrAndSwap :: DoubleVec -> Int -> Int -> Int -> DoubleVec
incrAndSwap vec i a b = runST $ do
  mvec <- V.thaw vec
  oldval <- MV.read mvec i                          -- 1
  MV.write mvec i (val + 1)                         -- 2
  MV.swap mvec a b
  V.freeze mvec

but being able to "condense" the two marked lines into one function, and be able to say:

incrAndSwap :: DoubleVec -> Int -> Int -> Int -> DoubleVec
incrAndSwap vec i a b = runST $ do
  mvec <- V.thaw vec
  incrAt mvec i
  MV.swap mvec a b
  V.freeze mvec

Basically, write that incrAt i function.

I've tried copying the type signature of MV.write but I haven't been able to get anything to work with the type signatures; nothing compiles.

Here is my most recent attempt

import Control.Monad.Primitive

type MDoubleVec s = MV.STVector s Double

incrAt :: (PrimMonad m) => MDoubleVec (PrimState m) -> Int -> m ()
incrAt mvec i = MV.write mvec i (val + 1)
  where
    val = MV.read mvec i          -- val is stuck in monad m0

But I don't know how to get val out of the monad m0 -- which it's in, apparently, according to the compiler. Which makes sense.

Does anyone know how I can do this?

4

1 回答 1

3

您需要MV.read在 monad 内部进行操作m,并将其结果绑定到val. 基本上,这是获取原始代码的两行并逐字移动它们的问题:

incrAt :: (PrimMonad m) => MDoubleVec (PrimState m) -> Int -> m ()
incrAt path i = do
    val <- MV.read path i
    MV.write path i (val + 1)

顺便说一句,仅供参考,类型错误提到m0而不是m(起初可能令人困惑)的原因是,在您的代码中,没有任何东西将val定义的 monad 链接到您执行的 monad MV.read。但真正的问题是MV.readmonadic 所以你需要绑定它的结果才能在也是 monadic 中使用它MV.write

于 2013-06-29T06:37:18.910 回答