Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Happstack display a read file

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.

like image 407
Inaimathi Avatar asked Nov 02 '12 03:11

Inaimathi


1 Answers

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.

like image 174
Fixnum Avatar answered Sep 21 '22 02:09

Fixnum