如何使用MonadBaseControl
中的monad-control解除simpleHTTP
中定义的happstack-server功能?
simpleHTTP
的当前类型:
simpleHTTP :: ToMessage a
=> Conf -> ServerPartT IO a -> IO ()
simpleHTTPLifted
的预期类型:
simpleHTTPLifted :: (MonadBaseControl IO m, ToMessage a)
=> Conf -> ServerPartT m a -> m ()
我目前的尝试(不编译):
simpleHTTPLifted conf action =
liftBaseWith (\runInBase ->
let
fixTypes :: UnWebT m a -> UnWebT IO a
fixTypes c = runInBase c
in simpleHTTP conf (mapServerPartT fixTypes action)
)
请注意,类似的谜题在我的相关问题中:MonadBaseControl: how to lift ThreadGroup
我想了解一般如何提升这些功能以及在提供这种类型拼图时采取的常规步骤是什么?
编辑:我想我需要一个(StM m a -> a)
类型的函数。 restoreM
非常接近,但没有成功。我还发现了fixTypes
的丑陋版本:
fixTypes :: UnWebT m a -> UnWebT IO a
fixTypes c = do
x <- newIORef undefined
_ <- runInBase (c >>= liftBase . writeIORef x)
readIORef x
这依赖于IO作为基础monad,这不是最佳解决方案。
答案 0 :(得分:1)
我认为你不能解除任何MonadBaseControl IO m
的问题。我们可以使用m
个。{/ p>
UnWebT m
与WebT m
同构,后者有MonadTransControl
个实例。您可以使用WebT
和mkWebT :: UnWebT m a -> WebT m a
与ununWebT :: WebT m a -> UnWebT m a
进行转换。
MonadBaseControl
围绕着一堆MonadTransControl
转换器是一个花哨的包装器,它会使堆栈变平,以便运行和恢复状态一直发生在堆栈中,并一直重新备份。您可以通过了解MonadBaseControl
了解MonadTransControl
,我将在此简要介绍一下:
class MonadTrans t => MonadTransControl t where
data StT t :: * -> *
liftWith :: Monad m => (Run t -> m a) -> t m a
restoreT :: Monad m => m (StT t a) -> t m a
type Run t = forall n b. Monad n => t n b -> n (StT t b)
该课程使用liftWith
,&#34;我将提供在t m
中运行m
的临时方法,您可以使用该方法在m
中构建操作{1}},我将依次运行。&#34; StT
类型的结果显示,&#34;我在t m
中为m
生成的t m
项内容的结果通常不会在{{1}中提供}};我需要在某个地方保存我的州,如果你想要结果,你必须给我机会恢复我的状态。&#34;
另一种说同样的事情的方式是,&#34;我可以暂时解开基础monad&#34;。实施fixTypes
的问题简化为&#34;鉴于我们可以暂时从WebT
打开m
,并暂时从{{1}展开m
我们可以永久地从IO
打开m
吗?&#34;除了IO
的能力之外,答案几乎肯定是#34; no&#34;。
我怀疑存在IO
这样的&#34;丑陋的&#34; m
将执行可怕的操作,例如从不调用fixTypes
,从而返回writeIORef
或异步执行代码,因此在undefined
之后调用writeIORef
。我不确定。由于readIORef
创建的操作可能从未在这种退化情况下使用,因此理由很复杂。
如果monad liftBaseWith
的状态为Comonad
并因此具有simpleHttp
函数,则应该有一种方法可以在没有IO
技巧的情况下提升m
}。例如,extract :: StM m a -> a
基本上有StateT s m
。
StM s a ~ (s, a)
在实践中,这不是非常有用,因为旧版monad-control中定义的{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Happstack.Server.SimpleHTTP
import Control.Comonad
import Control.Monad.Base
import Control.Monad.Trans.Control
simpleHTTPLifted :: forall m a. (MonadBaseControl IO m, Comonad (StM m), ToMessage a)
=> Conf -> ServerPartT m a -> m ()
simpleHTTPLifted conf action =
liftBaseWith (\runInBase ->
let
fixTypes :: UnWebT m b -> UnWebT IO b
fixTypes = fmap extract . runInBase
in simpleHTTP conf (mapServerPartT fixTypes action)
)
不具有newtype
个实例,并且新版本中的类型为同义词monad-control不会将结果作为最后一个类型参数。例如,在最新版本的monad-control Comonad
。