This is the first time I’m playing with Monad Transformers. This is a simple happstack app.
{-# 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)
I would like to be able to change hello so it can read some global config data using ReaderT. Let’s just say the config is a string to keep it simple
type NewMonad = ReaderT L.ByteString (ServerPartT IO)
runNewMonad :: NewMonad a -> L.ByteString -> ServerPart a
runNewMonad k c = runReaderT k c
How do I change hello so it can use ask? I’m not sure what the type would be. NewMonad Response isn’t quite right, because ok returns a ServerPart Response.
How do I change main so that serve works? It expects a ServerPart Response.
In fact,
NewMonad Responseis the correct type forhello; you just need to useliftto transform an action in the underlying monad to one in the transformer. For example:In general,
i.e., if you have a monadic action, then you turn it into an action in any monad transformer over that monad. This is the definition of a monad transformer: it can transform over any monad, and embed actions of that monad.
It seems that restricting all the monadic actions to one specific monad — rather than using typeclasses to work in any appropriate monad — is one of the simplifications happstack-lite uses compared to the full Happstack, which has this type for
ok:With this type, assuming appropriate instances are declared for the standard transformers, you could just use
okdirectly inMyMonad.As for
main, you need to eliminate theReaderTlayer, leading a aServerPart Responsethat you can pass toserve:(This would cause problems if you were using a monad carrying state that you wanted to change over the course of many requests, since
serve‘s type is too restrictive to support such state threading (without manually encoding it withIORefs or similar); possibly the unrestricted Happstack has the ability to do this, but it’d likely be very brittle anyway, as you shouldn’t really be relying on the order requests are processed in like that.)