Haskell ST Monad 中的 IO Monad
Haskell IO Monad in ST Monad
我想我有一个简单的问题,但我无法解决它:
我想创建一个向量,在此向量上调用 FFI 并 return 它。
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
现在,VSM.unsafeWith return 是一个 IO,这是在 ST Monad 中。但是如果我使用 ioToST 或 liftIO 我会遇到以下问题:
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)
知道如何将 unsafeWith
转换为正确的 Monad 吗?我看到IO和ST都是Prim-Monad,应该可以转换吧?
对于 FFI 应用程序,通常最简单的方法是完全不理会 ST
并在 IO
中进行所有操作。如果你必须有一个纯接口(并且你的 FFI 函数实际上在需要的方式上是纯的),你可以调用 unsafePerformIO
来提供一个纯接口。
但是,我想我会避免像您在这里所做的那样写 withCarray
。抽象很好,但是通过传递 not-suitably-behaving 回调很容易被误用。如果你必须拥有它,至少将它命名为 unsafeWithCarray
并留下黑线鳕明确说明在什么情况下它是安全的。
我想我有一个简单的问题,但我无法解决它: 我想创建一个向量,在此向量上调用 FFI 并 return 它。
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
现在,VSM.unsafeWith return 是一个 IO,这是在 ST Monad 中。但是如果我使用 ioToST 或 liftIO 我会遇到以下问题:
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)
知道如何将 unsafeWith
转换为正确的 Monad 吗?我看到IO和ST都是Prim-Monad,应该可以转换吧?
对于 FFI 应用程序,通常最简单的方法是完全不理会 ST
并在 IO
中进行所有操作。如果你必须有一个纯接口(并且你的 FFI 函数实际上在需要的方式上是纯的),你可以调用 unsafePerformIO
来提供一个纯接口。
但是,我想我会避免像您在这里所做的那样写 withCarray
。抽象很好,但是通过传递 not-suitably-behaving 回调很容易被误用。如果你必须拥有它,至少将它命名为 unsafeWithCarray
并留下黑线鳕明确说明在什么情况下它是安全的。