这是我第一次玩Monad Transformers。这是一个简单的happstack应用程序。
{-# LANGUAGE OverloadedStrings #-}
import Happstack.Lite
import qualified Data.ByteString.Lazy.Char8 as L
main :: IO ()
main = do
serve Nothing hello
hello :: ServerPart Response
hello = do
ok $ toResponse ("Hello" :: L.ByteString)我希望能够更改hello,这样它就可以使用ReaderT读取一些全局配置数据。为了简单起见,假设配置是一个字符串
type NewMonad = ReaderT L.ByteString (ServerPartT IO)
runNewMonad :: NewMonad a -> L.ByteString -> ServerPart a
runNewMonad k c = runReaderT k c如何更改hello以便它可以使用ask?我不确定会是什么类型。NewMonad Response并不完全正确,因为ok返回一个ServerPart Response。
如何更改main才能使serve正常工作?它需要一个ServerPart Response。
发布于 2012-01-26 12:46:42
实际上,NewMonad Response是hello的正确类型;您只需要使用lift将底层monad中的操作转换为转换器中的操作即可。例如:
hello :: NewMonad Response
hello = do
foo <- ask
lift . ok $ toResponse foo总体而言,
lift :: (MonadTrans t, Monad m) => m a -> t m a也就是说,如果你有一个单子动作,那么你就把它变成了这个单子上的任何单子转换器中的一个动作。这是monad transformer的定义:它可以在任何monad上转换,并嵌入该monad的操作。
似乎将所有的单一操作限制在一个特定的monad上-而不是使用类型类在任何适当的monad中工作-与完整的Happstack相比,Happstack lite使用的是简化之一,后者具有this type for ok
ok :: (FilterMonad Response m) => a -> m a对于这种类型,假设为标准转换器声明了适当的实例,您可以直接在MyMonad中使用ok。
至于main,您需要去掉ReaderT层,生成一个可以传递给serve的ServerPart Response
main :: IO ()
main = do
serve Nothing $ runNewMonad hello ("Hello" :: L.ByteString)(如果您使用的是monad承载状态,而您希望在许多请求的过程中更改它,这将会导致问题,因为serve的类型限制太多,无法支持这种状态线程处理(不需要使用IORef或类似的手动编码);可能不受限制的Happstack能够做到这一点,但它很可能非常脆弱,因为您不应该真正依赖于这样处理请求的顺序。)
https://stackoverflow.com/questions/9014018
复制相似问题