How to use "IO String" as an HTTP response in Happstack? - haskell

I'm retrieving data from a database using HDBC, then trying to send this data to a web client using Happstack.
myFunc :: Integer -> IO String
myFunc = ... fetch from db here ...
handlers :: ServerPart Response
handlers =
do decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
msum [
dir "getData" $ ok $ toResponse $ myFunc $ toInteger 1
]
mainFunc = simpleHTTP nullConf handlers
When I build the above code I get this error:
No instance for (ToMessage (IO String)) arising from a use of
`toResponse'
What did I try ?
I tried to convert the IO String to String (using liftIO for example).
I tried to find any similar questions here.
I tried to find a similar example in the Happstack Crash Course.
I googled all related keywords in all different combinations.
Thanks in advance.

You have to design your handlers around the fact that fetching from a database is a magical action that may not give you what you expect. (For example, your database may crash.) This is why its result is served as an IO, which is a particular case of a monad.
A monad is a jar with a very narrow neck, so narrow even that, once you put something in there, you cannot unput it. (Unless it happens to also be a comonad, but that's a whole another story and not the case with IO nor with ServerPart.) So, you would never convert an IO String to a String. Not that you can't, but your program would become incorrect.
Your case is kind of tricky as you have two monads at play there: IO and ServerPart. Fortunately, ServerPart builds upon IO, it is " larger " and can, in a sense, absorb IO: we can put some IO into a ServerPart and it will be a ServerPart still, so we may then give it to simpleHTTP. In happstack, this conversion may be done via require function, but there is a more general solution as well, involving monad transformers and lift.
Let's take a look at the solution with require first. Its type (simplified to our case) is:
IO (Maybe a) -> (a -> ServerPart r) -> ServerPart r
— So, it takes an IO jar with some argument and makes it suitable for a function that lives in the ServerPart jar. We just have to adjust types a bit and create one lambda abstraction:
myFunc :: Integer -> IO (Maybe String)
myFunc _ = return . Just $ "A thing of beauty is a joy forever."
handlers :: ServerPart Response
handlers = require (myFunc 1) $ \x ->
do decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
msum [
dir "getData" $ ok $ toResponse x
]
mainFunc = simpleHTTP nullConf handlers
As you see, we have to make 2 modifications:
Adjust myFunc so that it returns Maybe, as necessitated by require. This is a better design because myFunc may now fail in two ways:
As a Maybe, it may return Nothing, which means 404 or the like. This is rather common a situation.
As an IO, it may error out, which means the database crashed. Now is the time to alert the DevOps team.
Adjust handlers so that myFunc is external to them. One may say more specifically: abstract myFunc from handlers. This is why this syntax is called a lambda abstraction.
require is the way to deal with monads in happstack specifically. Generally though, this is just a case of transforming monads into larger ones, which is done via lift. The type of lift (again, simplified), is:
IO String -> ServerPart String
So, we can just lift the myFunc 1 :: IO String value to the right monad and then compose with >>=, as usual:
myFunc :: Integer -> IO String
myFunc _ = return $ "Its loveliness increases,.."
handlers :: ServerPart Response
handlers = lift (myFunc 1) >>= \x ->
do decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
msum [
dir "getData" $ ok $ toResponse x
]
mainFunc = simpleHTTP nullConf handlers
As simple as that. I used the same lambda abstraction trick again, but you may as well use do-notation:
myFunc :: Integer -> IO String
myFunc _ = return $ "...it will never pass into nothingness."
handlers :: ServerPart Response
handlers = do
x <- lift (myFunc 1)
decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
msum [
dir "getData" $ ok $ toResponse x
]
mainFunc = simpleHTTP nullConf handlers
P.S. Returning to the story of large and small jars: you can put IO into ServerPart precisely because ServerPart is also an IO monad — it is an instance of the MonadIO class. That means that anything you can do in IO you can also do in ServerPart, and, besides general lift, there is a specialized liftIO function that you can use everywhere I used lift. You are likely to meet many other monads out there that are instances of MonadIO as it's a handy way of structuring code in large applications.
In your particular case, I would stick with the require way nevertheless because I think it's how the designers of happstack meant it to be done. I'm not particularly knowledgeable about happstack though, so I may be wrong.
That's it. Happy hacking!

Related

Haskell Monads and the liftIO I don't get it

Hello community thank you for your time.
I have an error and I am not sure what the error is, but what I think the problem is:
There is no IO transformer from ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO) to Web.Scotty.Internal.Types.ScottyT.
But I wondering why the compiler works with ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO). That's why I am working just with String and I removed all occurrences of {-# LANGUAGE OverloadedStrings #-} but still get the error. On the other hand, this should be IO [String], shouldn't it?
And as you can mention I don't really know what ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO) is.
At another place, I already use liftIO successfully for an a -> IO String function. And I think I use them the same way.
I think I get slowly a feeling for what a monad is, but not quite sure. I don't really know why I have to use a lift function at all.
Error message:
• No instance for (MonadIO
(Web.Scotty.Internal.Types.ScottyT
text-1.2.4.1:Data.Text.Internal.Lazy.Text IO))
arising from a use of ‘liftIO’
• In a stmt of a 'do' block:
paths <- liftIO $ getAllFilePaths2 path
In the expression:
do paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths
In an equation for ‘pathsToScotty2’:
pathsToScotty2 path
= do paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths
|
49 | paths <- liftIO $ getAllFilePaths2 path
Where the error occurred:
import Control.Monad.IO.Class
...
pathsToScotty2 :: String -> ScottyM ()
pathsToScotty2 path = do
paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths
getAllFilePaths2 :: String -> IO [String]
getAllFilePaths2 dir = do
putStrLn dir
isFile <- doesFileExist dir
if isFile
then return [dir]
else do
dirs <- listDirectory dir
foldl foldHelper2 (return []) $ map (\d -> show $ mconcat [dir, "/",d ]) dirs
foldHelper2 :: IO [String] -> String -> IO [String]
foldHelper2 ps path = do
paths <- ps
newPaths <- getAllFilePaths2 path
return (paths ++ newPaths)
Truly understanding monads takes time, practice, and patience, but it shouldn't be too hard to understand the need for liftIO by examining your types.
First off, the type of liftIO is MonadIO m => IO a -> m a. This means that the function can convert any IO action into an action in the monad m so long as m has an instance of MonadIO. In theory, this can only be implemented if m has some way of processing IO actions, so this function is embedding the given action into the m monad.
You're definitely in the right sort of place to use liftIO, so why isn't it working? That is, you have a value getAllFilePaths2 path of type IO [String], and you'd like it to be a value of type ScottyM [String] — this indeed seems like a good place to use liftIO. However, ScottyM is not an instance of MonadIO, as that error message you saw is trying to tell you, so you can't use liftIO.
This may seem crazy—can you really not embed IO actions into ScottyM?—but there's actually a good reason for this. What happens if the IO action throws an error? Does your whole web app crash? It would if you naively used liftIO. Instead, scotty provides the function liftAndCatchIO, which, as the docs describe, is "Like liftIO, but catch any IO exceptions and turn them into Scotty exceptions." This is the preferred way to embed IO actions into Scotty.
And here comes the final gotcha: Note that liftAndCatchIO actually produces values of type ActionM a, not ScottyM a. Additionally, there's no way to take a value in the ActionM monad and get it into the ScottyM monad. Instead, you need to use that value as an action. So, I'm not sure what pathsToScotty does, but it's very likely that you'll need to rewrite it.

Answer a request with 200 or 404 based on the content of `Maybe` using Servant

I'm currently trying to implement a simple web server with servant. At the moment, I have a IO (Maybe String) that I want to expose via a GET endpoint (this might be a database lookup that may or may not return a result, hence IO and Maybe). If the Maybe contains a value, the response should contain this value with a 200 OK response status. If the Maybe is Nothing, a 404 Not Found should be returned.
So far I was following the tutorial, which also describes handling errors using throwError. However, I haven't managed to get it to compile. What I have is the following code:
type MaybeAPI = "maybe" :> Get '[ JSON] String
server :: Server MaybeAPI
server = stringHandler
maybeAPI :: Proxy MaybeAPI
maybeAPI = Proxy
app :: Application
app = serve maybeAPI server
stringHandler :: Handler String
stringHandler = liftIO $ fmap (\s -> (fromMaybe (throwError err404) s)) ioMaybeString
ioMaybeString :: IO (Maybe String)
ioMaybeString = return $ Just "foo"
runServer :: IO ()
runServer = run 8081 app
I know this is probably more verbose than it needs to be, but I guess it can be simplified as soon as it is working. The problem is the stringHandler, for which the compilation fails with:
No instance for (MonadError ServerError []) arising from a use of ‘throwError’
So my question is: Is this the way to implement such an endpoint in Servant? If so, how can I fix the implementation? My Haskell knowledge is rather limited and I never used throwError before, so it's entirely possible that I'm missing something here. Any help is appreciated!
As I mentioned in my comment, the problem is that in the offending line:
stringHandler :: Handler String
stringHandler = liftIO $ fmap (\s -> (fromMaybe (throwError err404) s)) ioMaybeString
s is a Maybe String, so to use it as the second argument to fromMaybe, the first argument must be a String - and throwError is never going to produce a string.
Although you talked about your code perhaps being too verbose and you would look at simplifying it later, I think part of the problem here is that in this particular handler you are trying to be too concise. Let's try to write this in a more basic, pseudo-imperative style. Since Handler is a monad, we can write this in a do block which checks the value of s and takes the appropriate action:
stringHandler :: Handler String
stringHandler = do
s <- liftIO ioMaybeString
case s of
Just str -> return str
Nothing -> throwError err404
Note that throwError can produce a value of type Handler a for any type it needs to be, which in this case is String. And that we have to use liftIO on ioMaybeString to lift it into the Handler monad, else this won't typecheck.
I can understand why you might have thought fromMaybe was a good fit here, but fundamentally it isn't - the reason being that it's a "pure" function, that doesn't involve IO at all, whereas when you're talking about throwing server errors then you are absolutely unavoidably doing IO. These things essentially can't mix within a single function. (Which makes the fmap inappropriate too - that can certainly be used to "lift" a pure computation to work on IO actions, but here, as I've said, the computation you needed fundamentally isn't pure.)
And if you want to make the stringHandler function above more concise, while I don't think it's really an improvement, you could still use >>= explicitly instead of the do block, without making the code too unreadable:
stringHandler = liftIO ioMaybeString >>= f
where f (Just str) = return str
f Nothing = throwError err404

Infinite stream of effectful actions

I would like to parse an infinite stream of bytes into an infinite stream of Haskell data. Each byte is read from the network, thus they are wrapped into IO monad.
More concretely I have an infinite stream of type [IO(ByteString)]. On the other hand I have a pure parsing function parse :: [ByteString] -> [Object] (where Object is a Haskell data type)
Is there a way to plug my infinite stream of monad into my parsing function ?
For instance, is it possible to write a function of type [IO(ByteString)] -> IO [ByteString] in order for me to use my function parse in a monad?
The Problem
Generally speaking, in order for IO actions to be properly ordered and behave predictably, each action needs to complete fully before the next action is run. In a do-block, this means that this works:
main = do
sequence (map putStrLn ["This","action","will","complete"])
putStrLn "before we get here"
but unfortunately this won't work, if that final IO action was important:
dontRunMe = do
putStrLn "This is a problem when an action is"
sequence (repeat (putStrLn "infinite"))
putStrLn "<not printed>"
So, even though sequence can be specialized to the right type signature:
sequence :: [IO a] -> IO [a]
it doesn't work as expected on an infinite list of IO actions. You'll have no problem defining such a sequence:
badSeq :: IO [Char]
badSeq = sequence (repeat (return '+'))
but any attempt to execute the IO action (e.g., by trying to print the head of the resulting list) will hang:
main = (head <$> badSeq) >>= print
It doesn't matter if you only need a part of the result. You won't get anything out of the IO monad until the entire sequence is done (so "never" if the list is infinite).
The "Lazy IO" Solution
If you want to get data from a partially completed IO action, you need to be explicit about it and make use of a scary-sounding Haskell escape hatch, unsafeInterleaveIO. This function takes an IO action and "defers" it so that it won't actually execute until the value is demanded.
The reason this is unsafe in general is that an IO action that makes sense now, might mean something different if actually executed at a later time point. As a simple example, an IO action that truncates/removes a file has a very different effect if it's executed before versus after updated file contents are written!
Anyway, what you'd want to do here is write a lazy version of sequence:
import System.IO.Unsafe (unsafeInterleaveIO)
lazySequence :: [IO a] -> IO [a]
lazySequence [] = return [] -- oops, not infinite after all
lazySequence (m:ms) = do
x <- m
xs <- unsafeInterleaveIO (lazySequence ms)
return (x:xs)
The key point here is that, when a lazySequence infstream action is executed, it will actually execute only the first action; the remaining actions will be wrapped up in a deferred IO action that won't truly execute until the second and subsequent elements of the returned list are demanded.
This works for fake IO actions:
> take 5 <$> lazySequence (repeat (return ('+'))
"+++++"
>
(where if you replaced lazySequence with sequence, it would hang). It also works for real IO actions:
> lns <- lazySequence (repeat getLine)
<waits for first line of input, then returns to prompt>
> print (head lns)
<prints whatever you entered>
> length (head (tail lns)) -- force next element
<waits for second line of input>
<then shows length of your second line before prompt>
>
Anyway, with this definition of lazySequence and types:
parse :: [ByteString] -> [Object]
input :: [IO ByteString]
you should have no trouble writing:
outputs :: IO [Object]
outputs = parse <$> lazySequence inputs
and then using it lazily however you want:
main = do
objs <- outputs
mapM_ doSomethingWithObj objs
Using Conduit
Even though the above lazy IO mechanism is pretty simple and straightforward, lazy IO has fallen out of favor for production code due to issues with resource management, fragility with respect to space leaks (where a small change to your code blows up the memory footprint), and problems with exception handling.
One solution is the conduit library. Another is pipes. Both are carefully designed streaming libraries that can support infinite streams.
For conduit, if you had a parse function that created one object per byte string, like:
parse1 :: ByteString -> Object
parse1 = ...
then given:
inputs :: [IO ByteString]
inputs = ...
useObject :: Object -> IO ()
useObject = ...
the conduit would look something like:
import Conduit
main :: IO ()
main = runConduit $ mapM_ yieldM inputs
.| mapC parse1
.| mapM_C useObject
Given that your parse function has signature:
parse :: [ByteString] -> [Object]
I'm pretty sure you can't integrate this with conduit directly (or at least not in any way that wouldn't toss out all the benefits of using conduit). You'd need to rewrite it to be conduit friendly in how it consumed byte strings and produced objects.

How to pass HTTP request parameter to quickQuery?

I'm using Happstack to receive some parameters from an HTTP request then pass these parameters to a function that will retrieve data from the database and return this data in the HTTP response as follow:
myFunc :: IO String
myFunc = do r <- look "personId"
conn <- connectODBC "... my connection string ...";
vals <- quickQuery conn ("SELECT Name FROM Person where Id = ?") [(toSql r)];
return (processData vals)
handlers :: ServerPartT IO Response
handlers = do
x <- liftIO (myFunc);
decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
msum [
dir "getData" $ ok $ toResponse x
, ... other handlers ...
]
mainFunc = simpleHTTP nullConf handlers
But when I build the above code I get the following error:
No instance for (HasRqData IO) arising from a use of `look'
In a stmt of a 'do' block: r <- look "personId"
After reading questions on similar issues (like this one) I think I have to include HasRqData constraint somewhere, but I couldn't learn where and how.
As you may have guessed, this is too an issue with monads. There are a handful of them in happstack (HasRqData, among others), so you may well consider it a complicated case.
Let us begin with the innocent-looking look function.
look :: (Functor m, Monad m, HasRqData m) => String -> m String
Indeed, there is a non-trivial constraint HasRqData. Let us ask ourselves: what monads HaveRqData? (It so happens that IO has not!)
class HasRqData m where
...
Instances
HasRqData RqData
(MonadIO m, MonadPlus m) => HasRqData (ServerPartT m)
...
The other instances are derivative of these first two, so, it looks like we have to consider these two options first.
The RqData has limited effects — you can only do look and its derivatives, extracting information from the request at hand. As we want to also have other effects — querying the database, for one, — this is not enough for us.
The ServerPartT m is the general form of the same old friend of ours, ServerPart ≡ ServerPartT IO. It happens that it also HasRqData. This is not a coincidence, but rather an implication of the design of happstack — looks like the authors meant us to use this single monad everywhere, unless we need particular granularity. So, let's give it a try.
myFunc :: ServerPart String
myFunc = do r <- look "personId"
return undefined
This compiles.
Now, we don't even need to lift myFunc in handlers — our previous predicament solved itself. We will need to lift our access to the database though, by the same jar logic we discussed before.
I believe you can figure the details by yourself. In any case, let me know how it works out!

"Truly" lazy IO in Haskell

Consider the fragment -
getLine >>= \_ -> getLine >>= putStr
It does the reasonable thing, asking for a string twice, and then printing the last input. Because the compiler has no way of knowing what outside effects getLine has, it has to execute both of them, even though we throw away the result of the first one.
What I need is to wrap the IO Monad into another Monad (M) that allows IO computations to be effectively NOPs unless their return values are used. So that the program above could be rewritten as something like -
runM $ lift getLine >>= \_ -> lift getLine >>= lift putStr
Where
runM :: M a -> IO a
lift :: IO a -> M a
And the user is asked for input only once.
However, I cannot figure out how to write this Monad to achieve the effect I want. I'm not sure if it's even possible. Could someone please help?
Lazy IO is usually implemented using unsafeInterleaveIO :: IO a -> IO a, which delays the side effects of an IO action until its result is demanded, so we'll probably have to use that, but let's get some minor problems out of the way first.
First of all, lift putStr would not type check, as putStr has type String -> IO (), and lift has type IO a -> M a. We'll have to use something like lift . putStr instead.
Secondly, we're going to have to differentiate between IO actions that should be lazy and those who should not. Otherwise the putStr will never be executed, as we're not using it's return value () anywhere.
Taking that into account, this seems to work for your simple example, at least.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import System.IO.Unsafe
newtype M a = M { runM :: IO a }
deriving (Monad)
lazy :: IO a -> M a
lazy = M . unsafeInterleaveIO
lift :: IO a -> M a
lift = M
main = runM $ lazy getLine >> lazy getLine >>= lift . putStr
However, as C. A. McCann points out, you should probably not use this for anything serious. Lazy IO is frowned upon already, as it makes it difficult to reason about the actual order of the side effects. This would make it even harder.
Consider this example
main = runM $ do
foo <- lazy readLn
bar <- lazy readLn
return $ foo / bar
The order of the two numbers are read in will be completely undefined, and may change depending on compiler version, optimizations or the alignment of the stars. The name unsafeInterleaveIO is long and ugly for a good reason: to remind you of the dangers of using it. It's a good idea to let people know when it's being used and not hide it in a monad.
There's no sensible way to do this, because to be quite honest it's not really a sensible thing to do. The entire purpose for introducing monadic I/O was to give a well-defined ordering to effects in the presence of lazy evaluation. It is certainly possible to throw that out the window if you really must, but I'm not sure what actual problem this would solve other than making it easier to write confusingly buggy code.
That said, introducing this sort of thing in a controlled fashion is what "Lazy IO" already does. The "primitive" operation for that is unsafeInterleaveIO, which is implemented roughly as return . unsafePerformIO, plus some details to make things behave a bit nicer. Applying unsafeInterleaveIO to everything, by hiding it in the bind operation of your "lazy IO" monad, would probably accomplish the ill-advised notion you're after.
What you are looking for isn't really a monad, unless you want to work with unsafe stuff like unsafeInterleaveIO.
Instead, a much cleaner abstraction here is Arrow.
I think, the following could work:
data Promise m a
= Done a
| Thunk (m a)
newtype Lazy m a b =
Lazy { getLazy :: Promise m a -> m (Promise m b) }

Resources