MonadBaseControl:如何从Happstack中提取simpleHTTP?

时间:2015-01-01 19:01:55

标签: haskell monads monad-transformers

如何使用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,这不是最佳解决方案。

1 个答案:

答案 0 :(得分:1)

我认为你不能解除任何MonadBaseControl IO m的问题。我们可以使用m个。{/ p>

一般

UnWebT mWebT m同构,后者有MonadTransControl个实例。您可以使用WebTmkWebT :: UnWebT m a -> WebT m aununWebT :: 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技巧

我怀疑存在IO这样的&#34;丑陋的&#34; m将执行可怕的操作,例如从不调用fixTypes,从而返回writeIORef或异步执行代码,因此在undefined之后调用writeIORef。我不确定。由于readIORef创建的操作可能从未在这种退化情况下使用,因此理由很复杂。

对于Comonads

如果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