gpt4 book ai didi

haskell - 将 ST monad 重新打扮成类似于 State monad 的东西

转载 作者:行者123 更新时间:2023-12-05 00:47:54 26 4
gpt4 key购买 nike

场景如下:Given 是一个 C 库,其核心是一些结构,其上的操作由大量 C 函数提供。

第一步:使用 Haskell 的 FFI创建一个包装器。它具有 myCLibInit :: IO MyCLibObj 等功能, myCLibOp1 :: MyCLibObj -> ... -> IO () , 等等。 MyCLibObj是一个不透明类型,带有(并隐藏)一个 PtrForeignPtr到实际的 C 结构,例如,如 wiki 中所示或在 RWH ch. 17 .

第二步:使用 unsafeIOToST来自 Control.Monad.ST.Unsafe 转换所有 IO行动到 ST 行动。这是通过引入类似的东西来完成的

 data STMyCLib s = STMyCLib MyCLibObj

然后包装所有 IO ST 中的函数函数,例如:
myCLibInit' :: ST s (STMyCLib s)
myCLibInit' = unsafeIOToST $ STMyCLib <$> myCLibInit

这允许编写反射(reflect)使用类似 OO 的 C 库的命令式程序,例如:
doSomething :: ST s Bool
doSomething = do
obj1 <- myCLibInit'
success1 <- myCLibOp1' obj1 "some-other-input"
...
obj2 <- myCLibInit'
result <- myCLibOp2' obj2 42
...
return True -- or False

main :: IO ()
main = do
...
let success = runST doSomething
...

第三步:通常在多个 MyCLibObj 上混合操作是没有意义的。在一个做 block 。例如,当 C 结构是(或应该被认为是)单例实例时。在 doSomething 中做类似的事情以上要么是 absurd 的,要么是完全禁止的(例如,当 C 结构是 static 时)。在这种情况下,语言类似于 State 之一monad 是必要的:
doSomething :: ResultType
doSomething = withMyCLibInstance $ do
success <- myCLibOp1'' "some-other-input"
result <- myCLibOp2'' 42
...
return result

在哪里
withMyCLibInstance :: Q a -> a

这导致了 问题 : ST s a怎么可能monad 被重新打扮成更类似于 State 的东西单子(monad)。由于 withMyCLibInstance将使用 runST函数新的 monad,我们称之为 Q (对于“问题”),应该是
newtype Q a = Q (forall s. ST s a)

这对我来说看起来很奇怪。我已经在努力实现 Functor Q 的实例,更不用说 ApplicativeMonad . ST s 实际上已经是一个 monad,但是状态 s不能逃避 ST monad,因此 forall s. ST s a .这是摆脱 s 的唯一方法因为 runST :: (forall s. ST s a) -> a , 和 withMyCLibInstance只是一个 myCLibInit'后跟 runST .但不知何故,这不合适。

处理第 3 步的正确方法是什么?我应该执行第 2 步,还是滚动我的 Q就在第 1 步之后?我的感觉是这应该很简单。 ST monad 拥有我所需要的一切, Q只需要以正确的方式设置...

更新 1:步骤 3 中的单例和静态结构示例不是很好。如果两个这样的 do block 并行执行,可能会发生非常糟糕的事情,即两个 do block 将并行处理同一个 C 结构。

最佳答案

您可以使用阅读器效果访问单例,仅在 run 中实例化它。功能:

newtype MyCLibST s a = MyCLibST { unMyCLibST :: ReaderT (STMyCLib s) (ST s) a }

runMyCLibST :: (forall s. MyCLibST s a) -> a
runMyCLibST m = runST (myCLibInit >>= runReaderT (unMyCLibST m))

-- Wrap the API with this.
unsafeMkMyCLibST :: (MyCLibObj -> IO a) -> MyCLibST s a
s应该作为 MyCLibST 的参数出现如果您想继续访问其他 ST可变引用和数组等功能。

关于haskell - 将 ST monad 重新打扮成类似于 State monad 的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50663615/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com