I use servant 0.19, so no the type RawM. I have a handler:
hnd :: Something -> ServerT Raw Handler
hnd Something {..} = do
-- p <- readIORef somePath -- COULDN'T MATCH TYPE "IO b0" WITH "Tagged Handler Application"
let stSet = defaultFileServerSettings "a/b/c"
serveDirectoryWith stSet
which is described as an API's type: :<|> "some" :> Raw
I want to do IO operations in my hnd handler. How to do it with this servant version (without RawM)? Also, I'd be grateful if you show it with RawM too (though it is not important due to the used version 0.19).
Short answer. Try:
The longer answer is that
ServerTis a type family associated with theHasServertype class that maps API expressions to transformations of theHandlermonad to implement the API:>and:<|>combinators as well as individual endpoints. For a "normal" endpoint, likeGet, it maps the typeServerT (Get ...) Handlerto plain oldHandler.To implement
Raw,ServerT Raw Handleris mapped toTagged Handler Application. This is simply a WAIApplicationwhose type has beenTaggedwith theHandlermonad.Servant-supplied wrappers, like
serveDirectoryWith, are really just WAIApplications that have beenTagged:where
staticAppis the underlying static file servingApplicationfrom thewai-app-staticpackage.So, that means that the simplified handler:
is equivalent to:
and given that an
Applicationis actually aRequest -> (Response -> IO ResponseReceived) -> IO ResponseReceived, this is the same as:or:
where the
do-block is running in the plain oldIOmonad. In this form, it's now possible to do "normal" IO stuff, which is how I derived the short answer above.RawMfrom version 0.20 doesn't gain you much here. It mapsServantT RawM Handlerto a modified version of an application:which adds the ability to perform
Handleractions besidesIO, namely signaling a specificServerError. If you had a customHandlerT, it could be more useful. It wouldn't make it any easier to write yourhnd, though.