Re: laziness and functional middleware

1998-06-17 Thread Hans Aberg

At 07:54 +0100 98/06/17, Simon L Peyton Jones wrote:
>> 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.
...
>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.

  I think one can use different techniques when doing concurrent
programming: One is to set forth different processes, and rather imperative
waiting for them in a loop to finish, which is my guess is what SLPJ thinks
of here.

  But one can do something more functional: In this model, the arguments
are references which handshake with the function. The function sets off
threads for HTTPRequests and DataBaseVersions, and go idle; these threads
report back when they have something to report, and the stuff is processed
then.

  But I found it rather difficult to implement this style with POSIX (Java)
threads: It is hard to guarantee that the computations does not hang. What
I needed was to be able to guarantee that certain sequences in the
implementation cannot the halted in the middle, but that is not possible
with pre-emotive threads I think.

  Hans Aberg
  * Email: Hans Aberg 
  * Home Page: 
  * AMS member listing: 






Re: Garbage Collection in GreenCard/RedCard/HaskellCOM

1998-06-17 Thread Sven Panne

S. Alexander Jacobson wrote:
> [...]
> However, Haskell/Com (built on top of Greencard?) seems to be able
> to propagate garbage collection information from Haskell to C so that
> when a Haskell/COM Object is no longer in use, there is some
> functionality decrements its reference counter automatically.
> 
> How does this work?  and can dima use this mechamism to free queries
> when they are no longer needed? ..allowing database queries outside
> the IOMonad?
> [...]

In GHC there is the ForeignObj data type, see sec. 5.4 of the GHC user
manual: In addition to a pointer outside the Haskell world (an Addr in
GHC-speak) it carries around a function pointer to a finalization
routine. The idea is essentially the same as e.g. Java's finalize()
method: When the garbage collector decides that a ForeignObj is going
to be wiped away, the finalization routine gets a chance to do some
cleanup just before the ForeignObj dies. Although the creation of a
ForeignObj must happen in the IO monad

makeForeignObj :: Addr   -- object to be boxed up as a ForeignObj
   -> Addr   -- finaliser 
   -> IO ForeignObj

the ForeignObj itself can be happily handed around to "normal" functions.

Hugs provides ForeignObj, too, but I haven't used it there yet, but it
seems identical to GHC's ForeignObj. This raises an IMHO important
issue: Something like ForeignObj (and StablePtr, Addr, Posix stuff, to
be continued...) should *really* end up in Haskell's standard libs.
Admittedly, these are all things having very little to do with the
merry world of the lambda calculus, they are of crucial importance if
Haskell should be accepted as a non-toy language.

-- 
Sven PanneTel.: +49/89/2178-2235
LMU, Institut fuer Informatik FAX : +49/89/2178-2211
LFE Programmier- und Modellierungssprachen  Oettingenstr. 67
mailto:[EMAIL PROTECTED]D-80538 Muenchen
http://www.pms.informatik.uni-muenchen.de/mitarbeiter/panne





Re: Garbage Collection in GreenCard/RedCard/HaskellCOM

1998-06-17 Thread Simon L Peyton Jones

> I just reread Dima's answer to my query about the database access in
> particular and am confused.  Dima says that he can't allow queries
> outside the IOMonad because he has to worry about freeing memory (query
> output).  
> 
> However, Haskell/Com (built on top of Greencard?) seems to be able to
> propagate garbage collection information from Haskell to C so that
> when a Haskell/COM Object is no longer in use, there is some functionality
> decrements its reference counter automatically.
> 
> How does this work?  and can dima use this mechamism to free queries
> when they are no longer needed? ..allowing database queries outside
> the IOMonad?  

I think all you need is something like this:

query :: String -- The query
  -> [Result]   -- The result

query q = unsafePerformIO (do {
server <- connect "foo.bax.com";
result <- sendQuery server q;
disconnect server;
return result
  })

A use of unsafePerformIO :: IO a -> a   is a promise that the
enclosed action is indeed a function.  I.e. the proof obligation
is yours.  That's what you say you want here.

And, yes, the garbage collection should be OK.

Simon







Re: laziness and functional middleware

1998-06-17 Thread Simon L Peyton Jones


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





Re: laziness and functional middleware

1998-06-17 Thread S. Alexander Jacobson


On Wed, 17 Jun 1998, Simon L Peyton Jones wrote:
> What is "Strict".  If you said (x `seq` ask2) instead 
> of (ask2 (Strict x)) then you should get the behaviour you expect.

"x `seq` ask2" didn't worth but after a little more research, "ask2
`strict` x" did.
The general question is whether it is stylistically good or bad to use
strictness outside the IO Monad to sequence IO.  The documentation is
ambiguous.

> 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 am guessing that this answers that question.  Anyone know a URL? Or can
someone send me a copy?

> > 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.

Actually only HTTPRequests block.  I assume that myCGIFunction gets
blocked until it recieves an HTTPRequest.  Onces it gets an HTTPRequest,
it pulls a new DatabaseVersion (opens a transaction) from the database
version list.  The database version list may also block in which case the
HTTPClient willl have to wait for database contention to ease before
getting back a response.   

In the general case, I am assuming that sources block if they are event
driven and supply a new version if they are demand driven.  (it is like 
the difference between demand-pull and event-push content on the web e.g. 
http requests vs recieving subscription email).  If the programmer has a
function that takes two blocking inputs then I presume that it waits on
one and then it waits on another.   The programmer just wants the program
to wait until it has input on both before firing an output.  For example,
you might have a spam detector which watches for incoming email on two
separate accounts.  This detector should block until it has mail in both.
 
> 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.
 
I am actually assuming that the unix select call is embedded in whatever
process is supplying the list of http requests not in Haskell itself.
Haskell's waiting for HTTPRequests is more like waiting for the system to
supply the contents of a file or waiting for more input from a socket.  
On haskell's end, I would expect it just to block until it has input (in
the same way that I would expect the filecopy function in the tutorial to
block until it sees EOF).
Is this an incorrect assumption?  It seems to work for addtwo above.
 
> 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.

Yes.  You could view them as creating a file, writing the list to the file
and spinning off a process that consumes the contents of the file in the
way unix "tail -f" does. 
e.g.
dbsink dbupdates = do
somehandle <- createHandle
%createProcess on somehandle
write somehandle (map show dbpudates)

The difficulty is that sequence semantics mean that dbSink must complete
before httpSink completes resulting in a large memory leak and no
httpresponse ever being sent.  The parallel haskell people added "par" to
be like "seq".  A primitive likethis would solve the problem.

> 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 guess you are on top of this.  I will download the paper now.

-Alex-
___

S. Alexander Jacobson   i2x Media  
1-212-697-0184 voice1-212-697-1427 fax









Re: Exceptions and functions. Second round?

1998-06-17 Thread Fergus Henderson

On 16-Jun-1998, Greg Michaelson <[EMAIL PROTECTED]> wrote:
> In SML(sorry...), in:  handle 
>  is evaluated and any exception raised within it is handled by an
> appropriate handler in . If there isn't one then the exception
> is handled in the enclosing environment for the whole construct. Similarly,
> if an exception is raised in  then it is handled in the enclosing
> environment. So exception handling follows a stack based regime.
> 
> Instead, how about having  handle exceptions raised within itself 

You can do this quite easily:

expr1 `recursive_handle` expr2 =
expr1 `handle` (\ e -> expr2 e `recursive_handle` expr2)

(Here I'm using a version of `handle' where the handler is the 2nd argument.)

However, doing this might be a bad idea, I think, because if `expr2'
raises any exception, this could easily lead to an infinite loop.

> and also allowing mutually recursive handlers?

This is also allowed by the current proposal -- it's quite straightforward:

handler1 e = stuff1 `handle` handler2
handler2 e = stuff2 `handle` handler1

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
WWW:   |  of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.