gpt4 book ai didi

haskell - 将函数及其参数提升到不同的一元上下文

转载 作者:行者123 更新时间:2023-12-02 16:07:46 24 4
gpt4 key购买 nike

我不知道如何科学地准确地表述这个问题,所以我只是给你看一个例子。

我正在 StateT 中使用状态变压器。底层是IO 。里面StateT IO操作我需要使用alloca 。然而我举不起来allocaStateT IO因为它需要 (Ptr a -> IO a) 类型的参数虽然我要求它与 (Ptr a -> StateT IO MyState a) 的参数一起工作.

(但是,这是关于 monad 转换器的一般问题,而不是特定于 IOStateTalloca 。)

我想出了以下可行的解决方案:

-- for reference
-- alloca :: (Storable a) => (Ptr a -> IO b) -> IO b

allocaS :: (Storable a) => (Ptr a -> StateT s IO b) -> StateT s IO b
allocaS f = do
state <- get
(res, st) <- liftIO $ alloca $ \ptr -> (runStateT (f ptr) state)
put st
return res

但是,对我来说,我应该解构并重建StateT,这似乎是错误的。操作以便将其与 alloca 一起使用。另外,我不止一次地看到这种模式的某些变体,它并不总是像 StateT 那样简单和安全。 .

有更好的方法吗?

最佳答案

这可以使用 MonadBaseControl 来完成在 monad-control ,正是为此目的而设计的:

{-# LANGUAGE FlexibleContexts #-}
import Control.Monad
import Control.Monad.Trans.Control
import qualified Foreign.Ptr as F
import qualified Foreign.Marshal.Alloc as F
import qualified Foreign.Storable as F

alloca :: (MonadBaseControl IO m, F.Storable a) => (F.Ptr a -> m b) -> m b
alloca f = control $ \runInIO -> F.alloca (runInIO . f)

这个增强版的alloca可以与任何基于实现MonadBaseControlIO的monad堆栈一起使用,包括StateT s IO .

MonadBaseControl 的实例允许它们的单子(monad)值在基本单子(monad)(这里是IO)中编码,传递给基本单子(monad)中的函数(例如F .alloca),然后将它们重建回来。

另请参阅What is MonadBaseControl for?

套餐lifted-base包含许多提升为 MonadBaseControl IO 的标准 IO 函数,但 alloca 还不在其中。

关于haskell - 将函数及其参数提升到不同的一元上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25102588/

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