This is a Haskell newb question probably to do with the IO()
monad.
I've got a function in a Happstack.Server
program that generates a response for a file upload.
postFile = do methodM POST
decodeBody filePolicy
(tmp, name, meta) <- lookFile "upload"
ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta]
That works fine. Now, I'd like it to display the content of the uploaded file as well as its local tempname, original name and content-type metadata. I was assuming that since this is all taking place in a do
block, I could just
postFile = do methodM POST
decodeBody filePolicy
(tmp, name, meta) <- lookFile "upload"
contents <- readFile tmp
ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta, "\n\n", contents]
but that hands me a string of errors that seems to tell me something is up with the decodeBody
call.
...
/home/inaimathi/projects/happstack-tutorial/parameters.hs:23:15:
No instance for (Happstack.Server.Internal.Monads.WebMonad
Response IO)
arising from a use of `decodeBody'
Possible fix:
add an instance declaration for
(Happstack.Server.Internal.Monads.WebMonad Response IO)
In a stmt of a 'do' block: decodeBody filePolicy
In the expression:
do { methodM POST;
decodeBody filePolicy;
(tmp, name, meta) <- lookFile "upload";
contents <- readFile tmp;
.... }
In an equation for `postFile':
postFile
= do { methodM POST;
decodeBody filePolicy;
(tmp, name, meta) <- lookFile "upload";
.... }
...
I'm not sure what's going wrong here. Can anyone educate me?
EDIT3:
That'll learn me to jump to conclusions.
The additional errors I was getting were all due to improperly installed libraries. Clearing out my ~/.ghc
, then installing happstack
again fixed it.
No instance for (Happstack.Server.Internal.Monads.WebMonad
Response IO)
Translation: your do
-block is not the IO monad but some other monad. Fortunately, it turns out to be an instance of MonadIO:
class Monad m => MonadIO m where
liftIO :: IO a -> m a
As you see, such an instance simply provides a way to 'lift' IO actions from the IO monad into itself, so in your case you just need:
contents <- liftIO $ readFile tmp
The implementation of liftIO
obviously depends on m
, but in a typical monad transformer stack it uses lift
and liftIO
to get to the IO monad inside; see e.g., the implementations for the other monad transformers in the Transformers library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With