Alex,

> > main = do  input <- getContents
> >          putStr $ addTwo $ makeLines input
> 
> > addTwo lines = ask1++(ask2 (Strict x)) ++ (result (Strict y))
> >     where   x:y:xs = map read lines
> >             ask1   = "Enter an Integer: "
> >             ask2 _ = "Enter another Integer: "
> >             result _ = "Theis sum is "++show (x+y)++"\n"
> 
> > data (Eval a) => Strict a = Strict !a
> > makeLines text = 
> >  (takeWhile ('\n'/=) text): (makeLines $ tail (dropWhile ('\n'/=) text))
> 
> But this code doesn't work.  It prints all the text and then waits for
> input.  Shouldn't laziness guarantee that addTwo doesn't print "Enter
> another integer" until the user enters the first integer?  (that is what
> the file copy example in the tutorial implies) 

What is "Strict".  If you said (x `seq` ask2) instead 
of (ask2 (Strict x)) then you should get the behaviour you expect.
There's a critique of various I/O models in 

%A P Hudak
%A RS Sundaresh
%T On the expressiveness of purely-functional I/O systems
%R YALEU/DCS/RR-665, |DCS|, Yale University
%D March 1989

I don't know whether it got published anywhere.


> For example I am writing an application that handles HTTP transactions 
> and uses a database backend.
> Ideally, I would like to write cgifunctions of type:
> 
> myCGIFunction:: [HTTPRequest]->[DatabaseVersion]->
>                       ([HTTPResponse],[DatabaseChanges])
> 
> HTTPRequests come from _middleware_ that recieves http requests from the
> httpd and append them to a list. Attempts to get the next item in the
> HTTPRequest list block until requests come in to fill the list.
> 
> DatabaseVersions come from a driver that appends a new txnBegin object
> to a list.
> 
> The program would look something like:
> main = do 
>       (dbSource,dbSink) <- dbConnect "ODBC: someodbcurl"
>       (httpSource,httpSink) <- apacheConnect "urlToListenOn"
>       (httpResponses,dbUpdates) <- return $ myCGIFunction httpSource dbSource
>       dbSink dbUpdates
>       httpSink httpResponses

I gather that HTTPRequests and DataBaseVersions arrive 
asynchronously and unpredictably.  So how does myCGIFunction know
which list to probe first?  Whichever it chooses it may block on
one while there is data on the other. Unless I'm misunderstanding.

You need to be able to say "wait until there's input available
on one of these two ports, and tell me which".  Something like
the Unix select call.  GHC's Posix library has such a thing,
but you can't use it in the way you describe because myCGIFunction
is a pure function on lists.


So far as your dbSink is concerneds, presumably what you have in mind is that
(dbSink dbUpdates) spins off a concurrent process that pulls on dbUpdates and
sends them to the database.  Concurently, httpSink is doing the same.


In short, lots of concurrency and non-determinism.  Fine!  That's
what Concurrent Haskell is for.  You can find a paper saying what
Concurrent Haskell is intended for.
        http://www.dcs.gla.ac.uk/~simonpj/papers.html
(under "monads, state, and concurrency").

I hope this helps somewhat.

Simon


Reply via email to