简体   繁体   中英

Haskell IO Monad in ST Monad

I guess I have a simple problem, but I'm not able to solve it: I want to create a vector, call FFI on this vector and return it.

import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Storable.Mutable as VSM
withCarray :: Int -> (Ptr Float -> IO ()) -> (Vector Float)
withCarray n f = VS.create $ do
  v <- VSM.new n 
  VSM.unsafeWith v f
  return v

Now, VSM.unsafeWith returns an IO, and this is in the ST Monad. But if I use ioToST or liftIO I get the following problem:

 Couldn't match type ‘s’ with ‘RealWorld’
      ‘s’ is a rigid type variable bound by
        a type expected by the context:
          forall s. ST s (VSM.MVector s Float)
        at src/Interpolation.hs:(60,30)-(63,10)
      Expected type: ST s (VSM.IOVector Float)
        Actual type: ST s (VSM.MVector (PrimState (ST s)) Float)

Any idea, how I can convert the unsafeWith to the correct Monad? I saw that IO and ST are both Prim-Monads, so it should be possible to convert them, right?

For FFI applications, it's usually simplest not to bother with ST at all and do everything in IO . If you must have a pure interface (and your FFI function actually is pure in the way needed), you can call unsafePerformIO to give a pure interface.

However, I think I would shy away from writing withCarray as you have done here. Abstraction is nice, but this is too easy to accidentally misuse by passing a not-suitably-behaving callback. If you must have it, at the very least name it unsafeWithCarray and leave a Haddock explicitly stating under what circumstances it is safe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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