Re: UnHappy 55 tuple [was: Re: PrelTup]
Hi Sigbjorn, I had another look at the 55 tuple problem. And this time, I could find a short program that produces the error. ... I had a look at `PrelTup.lhs' and it seems to define tuples up to 37 tuples or so. Maybe this is the problem. What shall I do? Hack `PrelTup.lhs'? (Doesn't seem very attractive...) Yes, that's the problem. I've often thought of making tuples more generic, but it never seems worth the bother (which is, belive me, non-trivial). I think the simplest solution would be to transform big tuples into nested smaller tuples... but I havn't gotten around to doing it. You could do it yourself of course, or hack PrelTup... Sorry about this. I hate it when compilers embody arbitrary limits. Simon
minor bug and help with alpha-debian-linux ?
Hi Guys, First a small bug: then line 1185 of the ghc-2.10 configure script has a bug: it is 1185 if test `eval $cmd_string 2/dev/null` != "1"; then but should be 1185 if test x`eval $cmd_string 2/dev/null` != x"1"; then in case one uses egcs (as I do). Anyways, I want to make ghc 2.10 on my alpha. It runs Debian GNU/Linux. Fortunately, the alpha-dec-osf image works somewhat so I hope to be able to bootstrap. But please (1) tell me if you know of others who did this, and (2) put me on the ghc haskell mailing list! Ta, Kristoffer -- Kristoffer H?gsbro Rose, Ph.D., prof.associe [EMAIL PROTECTED] Laboratoire de l'Informatique du Parallelisme equipe PLUME, bureau LR5-026 Ecole Normale Superieure de Lyon; 46, Allee d'Italie; F-69364 Lyon 07 cedex phone: +33(0)4 7272 8642; fax:...8080http://www.ens-lyon.fr/~krisrose
Re: Exceptions are too return values!
On 15-Jun-1998, Peter White peter@galois wrote: On June 15, Fergus Henderson writes As noted earlier, things like heap overflow, and stack overflow are different from other kinds of exceptions. They can't be modelled using the domain-theoretic semantics. Rather, they reflect the failure of the operational semantics to accurately reflect the domain-theoretic semantics. Thus the treatment of these exceptions may need to be different to the treatment of ordinary exceptions. One of the advertisements of Haskell is that you can reason about your program, by performing mathematical proofs about the program. Haskell has gone a long way to incorporating IO and stateful computations in such a way that you still get referential transparency, and you can still reason about programs. If the operational semantics fails to reflect, the domain-theoretic semantics, then it would appear that the ability to reason about the programs dissappears. This is not the case here. The reason is that although the operational semantics are not complete w.r.t. the denotational (domain-theoretic) semantics, they are sound. That is, you can't use the denotational semantics to prove that your program won't get a heap overflow; but you can use them to prove that if your program doesn't get a resource failure like that, then it will compute the right answer. If you want to reason about resource limits, then you need to use an operational semantics, not the denotational semantics. I think it is a requirement upon a Haskell implementation to preserve the independence of threads by "localizing" the resources to the threads, such that each thread can predict by itself, independently of any other thread, whether its resources will be sufficient. I don't think this is desirable in the general case. I think it would be useful to *allow* threads to reserve resources, but often it is difficult to predict in advance exactly how much each thread will use, and frequently it is better to deal with resource failures when they arise. -- Fergus Henderson [EMAIL PROTECTED] | "I have always known that the pursuit WWW: http://www.cs.mu.oz.au/~fjh | of excellence is a lethal habit" PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.
Re: FW: Exceptions are too return values!
I thought about this problem some more, and I have realized that the problem of nondeterminacy for Haskell exceptions would in fact be considerably worse that I had previously considered. The trouble is that in the general case the problem is not just that the choice of which exception is raised is nondeterministic -- instead, it would be much worse: the choice of whether you raise an exception or loop forever can be also be nondeterministic. This occurs because of expressions such as `0/0 + loop'. Or, to take a more realistic (and nasty) example, `f 0' where `f x = 1/x + g x' where `g x' happens to loop if `x' is zero. I don't agree that this is a problem. If (g x) loops when x is zero then you should jolly well test for that: f x | x == 0= raise "x is zero" | otherwise = 1/x + g x I simply don't think it's reasonable to comletely prescribe the evaluation order of a lazy functional program. At the moment, Haskell has the fiction that a divide-by-zero exception and non-termination are the same value, i.e. bottom. That allows us to say that the behaviour of f x = 1/x + g x is identical regardless of whether "+" evaluates its first argument first or second. But we all know that the behaviour in these two cases is quite different: one prints a message and halts, and the other fails to terminate. So in this sense the behaviour of Haskell programs is already non-deterministic. The nice thing about the NDSet story is that it makes clear precisely where the non-determinism occurs. Equational reasoning is not impaired, nor is the implementation penalised. I think it's a great idea. So I appear to be in disagreement here with Alex, Amr, and Fergus about the importance of being able to say precisely which exception is raised. I'm quite content with knowing which *set* of exceptions can be raised. Ha! Simon
RE: FW: Exceptions are too return values!
At 11:06 +0200 98/06/16, Erik Zuurbier wrote: ... Exceptions are merely a way to structure the code, so that the main line and error handling can be neatly separated. This is the original idea, but I pointed out that exceptions are in fact much deeper: They can be used as a programming technique too, and further, many common language constructs (such as "return", "break", etc in C++) can be viewed as special cases of exception handling. Hans Aberg * Email: Hans Aberg mailto:[EMAIL PROTECTED] * Home Page: http://www.matematik.su.se/~haberg/ * AMS member listing: http://www.ams.org/cml/
RE: FW: Exceptions are too return values!
On Tue, 16 Jun 1998, Erik Zuurbier wrote: I have read many, but not all of the messages on this subject. Did any of those shed any light on the intended use of exceptions? Maybe that could explain the disagreement. I can imagine: 1) You use exceptions for debugging your program, with the goal (naive maybe) that none will ever be raised in the final program. 2) You learn to rely on the defined behaviour, deterministic or not, and the final program can be perfectly acceptable if it raises any number of exceptions as long as they are caught and handled in time. Exceptions are merely a way to structure the code, so that the main line and error handling can be neatly separated. There's a third case, I think: 3) You are writing code which may be reused (either by design or fortuitous circumstance); consequently if any of your `externally usable' functions can throw an exception, you can't rely upon the user reading and understanding you code to the degree that they appreciate all the nuances of exactly which exception was thrown in some intricate circumstance. (I think haskell is still a way from the C++ situation where there are distributed _binary libraries_ which can throw exceptions, so you can't assume you can even read the source.) Thus you have to deliberately make circumstances where knowing _exactly_ what the primary error is (rather than just that `an error occurred whilst doing this overall thing') exactly predictable yourself, strictifying code if necessary. cheers, dave email: [EMAIL PROTECTED] "Taught the wife some html. __Bad www.cs.bris.ac.uk/~tweed/pi.htm move__." -- Alan Cox work tel: (0117) 954-5253
Re: Exceptions are too return values!
On 15-Jun-1998, Fergus Henderson [EMAIL PROTECTED] wrote: On 12-Jun-1998, Scott Turner [EMAIL PROTECTED] wrote: At 14:40 1998-06-10 +0100, you wrote: Here's a reasonable design for exceptions in Haskell: * handle :: (String - IO a) - IO a - IO a You probably realized more quickly than I how this can leak exceptions. ... Is this considered a drawback? This kind of exception handling can "leak" exceptions, but not in the way you described. ... What I mean is main = do quotient - handle (const (return 0)) (return (0 / 0) -- Looks plausible -- but the exception isn't raised yet. print quotient -- Here the expression 0/0 is evaluated -- and the exception is raised with no handler. This is not correct. This example would print out `0' rather than raising an uncaught division by zero exception. I'm afraid I must retract those statements. Scott Turner was quite correct, and I was mistaken. My apologies! As Scott pointed out to me in personal email, SLPJ's definition of `handle' | * handle :: (String - IO a) - IO a - IO a | (handle h a) tries to perform the action a. | If doing so delivers a set of exceptional values then | apply the exception handler h to the string that names | one of them. It is not defined which of the exceptional | values is picked. means that it only catches exceptional values in the I/O action, not exceptional values in the return value. Regarding Scott's question Is this considered a drawback? my answer is still much the same -- yes, it's a drawback, but I'd place the blame more on laziness than exception handling. I consider it only a minor drawback, since the "leakage" can be avoided if you use a version of `handle' which is strict in the return value, e.g. strict_handle handler action = handle handler strict_action where strict_action = do value - action seq value return value -- or with `hyper_seq' instead of `seq' -- Fergus Henderson [EMAIL PROTECTED] | "I have always known that the pursuit WWW: http://www.cs.mu.oz.au/~fjh | of excellence is a lethal habit" PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.
Re: FW: Exceptions are too return values!
At 14:40 +0100 98/06/10, Simon L Peyton Jones wrote: Here's a reasonable design for exceptions in Haskell: A think one can use a monadic approach, as a monad (X, unit_X, bind_X): HaskellX - HaskellX where HaskellX is and extension of Haskell with exceptions. * A value of Haskell type T can be EITHER one of the values we know and love (bottom, or constructor, or function, depending on T), OR it can be a set of exceptional values. So this says that X(T) = T | Exception, where Exception is a type in HaskellX which labels objects in Haskell as exceptions. This monad is such as old Haskell code can always be run in the new HaskellX. * raise :: String - a (raise s) returns a single exceptional value, named by string s I would suggest that an exception could not just be a string, but any value in HaskellX. * All strict operations (case, +, etc) return the union of the exceptional values returned by their strict arguments For example, if both arguments to "+" return an exceptional value then "+" returns both. Similarly, any strict context. Actually, if a function f in Haskell has type T, and is altered so that it raises an exception, then its type becomes T | Exception. If a function g: A - B is altered to raise an exception, there is a difference between the types A - (B | Exception) and (A | Exception - B | Exception), but the monad is such that one can always simplify to the latter, and one can use the abbreviation (A - B) | Exception for the latter. So the type handling mechanism should not need to be that much more complicated: Just replace T with T | Exception if the function raises an exception. Functions that do not raise an exception can always be extended to this, T | Exception, on the fly when encountering an exception via the monad proeprties, so these functions need not get an altered type. * handle :: (String - IO a) - IO a - IO a (handle h a) tries to perform the action a. If doing so delivers a set of exceptional values then apply the exception handler h to the string that names one of them. It is not defined which of the exceptional values is picked. Then handle() should not only handle strings and IO, but any Exception (of course), and any action a. The handle function must be able to determine if it can handle the exception, so it should have a function f: Exception - Boolean as an extra argument; the exception is handled only if this evaluates to "true" for the exception it handles. Hans Aberg * Email: Hans Aberg mailto:[EMAIL PROTECTED] * Home Page: http://www.matematik.su.se/~haberg/ * AMS member listing: http://www.ams.org/cml/
Re: FW: Exceptions are too return values!
On 16-Jun-1998, Simon L Peyton Jones [EMAIL PROTECTED] wrote: [Fergus wrote:] I thought about this problem some more, and I have realized that the problem of nondeterminacy for Haskell exceptions would in fact be considerably worse that I had previously considered. The trouble is that in the general case the problem is not just that the choice of which exception is raised is nondeterministic -- instead, it would be much worse: the choice of whether you raise an exception or loop forever can be also be nondeterministic. This occurs because of expressions such as `0/0 + loop'. Or, to take a more realistic (and nasty) example, `f 0' where `f x = 1/x + g x' where `g x' happens to loop if `x' is zero. I don't agree that this is a problem. If (g x) loops when x is zero then you should jolly well test for that: f x | x == 0= raise "x is zero" | otherwise = 1/x + g x Simon, I'm sure that a really thorough programmer such as yourself would never forget to insert such a test. But, as was recently demonstrated on this mailing list ;-), I'm quite fallible. I'm sure there are many other fallible Haskell programmers around. To minimize the bugs in my programs, I use a lot of different tools and techniques. I write in languages that have a lot of static checking, so that the compiler will catch a lot of my mistakes. I get my colleagues to review my code. And last but not least, I test my code. For the kind of bug referred to above, static checking isn't going to help (at least not given the current state of the art -- no doubt improvements are possible). Code reviews would help, but my colleagues are fallible too. And this kind of bug is very difficult to test for. Not only is it difficult to construct test cases that exercise all the exceptional cases, even that is not sufficient, since it might work fine with one implementation and then fail with another. So, I don't think it is reasonable to say that this is not a problem. It may not be a big problem, but I do consider it a problem. Now, we can certainly debate the likely frequency of such bugs, and their cost, and compare this with the advantages and disadvantages of exception handling. In fact, it does seem likely that such bugs would be very rare. The cost of each such bug may be high, but if they occur infrequently enough, then the overall cost will be small. So maybe you just meant that it wasn't likely to be a significant problem in practice. If that was what you meant, then I'm inclined to agree with you. I simply don't think it's reasonable to comletely prescribe the evaluation order of a lazy functional program. Why not? Because it would inhibit optimization? This is true, but for some applications reliability (and hence determinism) is much more important than efficiency. For these applications, I think it would be reasonable to specify the behaviour exactly, even if it means giving up some optimization opportunities. Do you agree? Conversely, there are many applications for which efficiency is more important than determinacy, so for those applications I agree the behaviour should not be specified exactly. Fortunately a single language can support both kinds of applications, as I outlined in previous mail. At the moment, Haskell has the fiction that a divide-by-zero exception and non-termination are the same value, i.e. bottom. That allows us to say that the behaviour of f x = 1/x + g x is identical regardless of whether "+" evaluates its first argument first or second. But we all know that the behaviour in these two cases is quite different: one prints a message and halts, and the other fails to terminate. So in this sense the behaviour of Haskell programs is already non-deterministic. That's true, but since both the fatal error message and non-termination constitute program bugs, this is not so much of a worry. The nondeterminism doesn't make testing any more difficult, for example. -- Fergus Henderson [EMAIL PROTECTED] | "I have always known that the pursuit WWW: http://www.cs.mu.oz.au/~fjh | of excellence is a lethal habit" PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.
Exceptions and functions. Second round?
Tony Finch cites Hans Aberg, who comments the posting of Eric Zuurbier who writes that: "... Exceptions are merely a way to structure the code, so that the main line and error handling can be neatly separated." * This is the original idea, but I pointed out that exceptions are in * fact much deeper: They can be used as a programming technique too, * and further, many common language constructs (such as "return", * "break", etc in C++) can be viewed as special cases of exception * handling. [HA] Indeed, in Modula-3, RETURN and EXIT are defined in terms of exceptions. I like the idea of the non-deterministic exception system that has been proposed, but it'll be interesting to see how well it works in real life... Tony. I am afraid that we are repeating what has been already said, but OK, this is the essence of wisdom... I don't think that I would agree with such philosophy. "break" in C is nothing more than a structured "goto". Break from "switch" is just a jump, from a loop it might do some cleanup (if the loop index is stacked). "Return" is also a jump with the cleanup of the last instance frame. As we all know, all this can be represented by continuations, and this is a practical issue, not a statement that "all Turing machines are equal, only some are more equal than the others..." There is - in my opinion - nothing "exceptional" in *standard* imperative control structures. OK, I admit that I am a sinner myself, and I had written some small event-driven programs using (ppardonnez le mot) "longjump" in C, but I believe strongly that the functional programming community with the monadic religion etc. is much more close to the Truth. Jerzy Karczmarczuk Caen, France
RE: FW: Exceptions are too return values!
SLPJ writes: So I appear to be in disagreement here with Alex, Amr, and Fergus about the importance of being able to say precisely which exception is raised. I'm quite content with knowing which *set* of exceptions can be raised. I have read many, but not all of the messages on this subject. Did any of those shed any light on the intended use of exceptions? Maybe that could explain the disagreement. I can imagine: 1) You use exceptions for debugging your program, with the goal (naive maybe) that none will ever be raised in the final program. 2) You learn to rely on the defined behaviour, deterministic or not, and the final program can be perfectly acceptable if it raises any number of exceptions as long as they are caught and handled in time. Exceptions are merely a way to structure the code, so that the main line and error handling can be neatly separated. Erik Zuurbier
Re: Exceptions and functions. Second round?
At 14:01 +0200 98/06/16, Jerzy Karczmarczuk wrote: There is - in my opinion - nothing "exceptional" in *standard* imperative control structures. OK, I admit that I am a sinner myself, and I had written some small event-driven programs using (ppardonnez le mot) "longjump" in C, but I believe strongly that the functional programming community with the monadic religion etc. is much more close to the Truth. I think you are raising the issue of exceptions without handling it properly. :-) Of course, when leaping to the next level of abstraction, exceptions are as exceptional as irrational numbers are irrational and the imaginary complex unit is imaginary in the original linguistic semantic sense, that is, not at all. And C is a language whose trademark is the absence of logical structure described by theory, so what's done in that language is rather misleading if one wants to produce a new generation of languages admitting new abstractions for the convenience to people that can think in terms of abstractions and by that do more efficient work. In fact, the opposite seems to happen, the new concept of exceptions seems to fit those old imperative ad hoc structures into a nice single abstraction. As we sit here with a language, Haskell, which normally does not admit imperative structures, using exceptions might be a neat way to do it. Hans Aberg * Email: Hans Aberg mailto:[EMAIL PROTECTED] * Home Page: http://www.matematik.su.se/~haberg/ * AMS member listing: http://www.ams.org/cml/
Re: Exceptions are more than just return values!
At 12:15 +0100 98/06/16, Tony Finch wrote: I like the idea of the non-deterministic exception system that has been proposed, but it'll be interesting to see how well it works in real life... Perhaps one can have them both with handlers handle_absolutely and handle_maybe, so that user can play around with them both and compare. Hans Aberg * Email: Hans Aberg mailto:[EMAIL PROTECTED] * Home Page: http://www.matematik.su.se/~haberg/ * AMS member listing: http://www.ams.org/cml/
Re: Exceptions and functions. Second round?
[EMAIL PROTECTED] (Greg Michaelson) writes: In SML(sorry...), in: exp1 handle exp2 exp1 is evaluated and any exception raised within it is handled by an appropriate handler in exp2. 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 exp2 then it is handled in the enclosing environment. So exception handling follows a stack based regime. Instead, how about having exp2 handle exceptions raised within itself and also allowing mutually recursive handlers? No need to wire this into the semantics/implementation - it's easy to implement your "recursive catch" using the plain catch: rcatch :: IO a - (IOError - IO a) - IO a m `rcatch` h = m `catch` \err - (h err `catch` h) but notice that I call plain catch when invoking the handler - so we won't get into infinite loops. If infinite loops are what you want :-), then we have "really recursive catch" rrcatch :: IO a - (IOError - IO a) - IO a m `rrcatch` h = m `catch` \err - (h err `rrcatch` h) Yet another variant would be to invoke the handler up to 10 times (say) before giving up and invoking the outer handler. This might form a very nice inter-process communication mechanism, which may be recognised by people who have written interrupt driven multi-process systems. I sort of see how this might work - but I've only _read about_ such systems - not actually implemented them. Where could I find out more? Alastair ps I'm getting kinda worried about people talking about using the exception handling mechanism to implement various control constructs. While our non-deterministic semantics is (I hope) fine for writing robust programs, I can't see how to build __predictable__ control constructs on top of it and I have no desire to modify the implementation and semantics just so that you can do so. I also think we need to spend some time playing with the GHC-based implementation before we'll really know how it performs. Just how big a problem will it be if an optimiser transforms a program that would have raised an error into a program that enters an infinite loop and triggers a timeout? In some applications, this won't be a problem but it could be a real problem in others.
Re: Exceptions and functions. Second round?
In SML(sorry...), in: exp1 handle exp2 exp1 is evaluated and any exception raised within it is handled by an appropriate handler in exp2. 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 exp2 then it is handled in the enclosing environment. So exception handling follows a stack based regime. Instead, how about having exp2 handle exceptions raised within itself and also allowing mutually recursive handlers? This might form a very nice inter-process communication mechanism, which may be recognised by people who have written interrupt driven multi-process systems. It probably has horrendous semantic implications... Greg Michaelson
Garbage Collection in GreenCard/RedCard/HaskellCOM
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? -Alex- PS The answer to this question is related to my prior unanswered question on laziness and middleware. ___ S. Alexander Jacobson i2x Media 1-212-697-0184 voice1-212-697-1427 fax On Tue, 26 May 1998 [EMAIL PROTECTED] wrote: * SQL: many industrial strength databases provide a snapshot mode where the state of the database doesn't change for the duration of the connection. I accept that opening a connection may need to be within a do sequence. It doesn't make sense to me that SQL select queries should be. They are functions over a database datastructure in the same way one might write functions over lists. (based on looking at the ODBC lib from Dima Skvortsov [EMAIL PROTECTED]) I would respond to particularily this question as long as I am still working on this ODBC lib. (BTW note my new e-mail is address: [EMAIL PROTECTED], the one you mentioned above is not valid any more) Feel free to mail me if there are any problems/comments/... with this lib. Considering SQL queries that do not change state, it seems to me not so easy to get rid of putting them into monadic action. First of all you need to connect to database first, _then_ perform some SQL queries and _then_ disconnect. There is no sense in performing queries before connecting. Monad allows to synchronize these steps. Second, every SQL statement has its unique identifier (C type is HSTMT). It's created with function SQLAllocStmt and should be freed later with SQLFreeStmt. This identifier should be kept all the time to obtain query results or change parameters or run the query once more. Third, this identifier is not the only thing associated with a semi-stateless SQL statements. SQL statement identifier must be binded with memory buffers to obtain query results or set query parameters. Freeing this memory especially in case of fetching data is pretty difficult matter. Note that lazy list which represents the data being fetched can be evaluated to the end as well as left partly unevaluated. It depends on how many rows were fetched or how many elements of the list were binded within strict functions. Memory buffers should be freed when the list is fully evaluated or when the statement is closed. The best solution to that problem that I found required me to maintain an IO reference to the list of allocated memory with the SQL statement identifier. Obviously it's not possible without monad. Best regards, Dima Skvortsov
Re: Garbage Collection in GreenCard/RedCard/HaskellCOM
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? The year before I left Glasgow, I added some special GC extensions to GHC. When I arrived here, I added the same stuff into Hugs. The details are in a never-completed paper which is hanging off my home page (URL in signature) but here's an outline: ForeignPtrs (nee MallocPtrs) point from Haskell into C StablePtrs point from C into Haskell ForeignPtr is just like Addr (the GHC/Hugs name for void*) except that when the garbage collector deletes a ForeignPtr it calls a deallocation function to let C know what's happening. This deallocation function might be "free" if the ForeignPtr is a block of memory or it might be "fclose" if it's a FILE* or it might be a piece of code you wrote yourself. (Each ForeignPtr can have a different freeing function if you want.) (ForeignPtrs are often called Weak Pointers in other languages) Since C doesn't have automatic GC, StablePtrs are explicitly allocated and deallocated. As long as a stable ptr exists, the Haskell GC knows that the object is in use and doesn't deallocate it. Once the stable ptr is free'd the GC is free to deallocate it (assuming it's not needed for any other reason). ForeignPtrs seem to work ok for abundant resources like memory. When using scarce resources, code like the following is quite common: if (i=NUM_HANDLES) { /* If at first we don't*/ garbageCollect(); /* succeed, garbage collect*/ for (i=0; iNUM_HANDLES nonNull(handles[i].hcell); ++i) ; /* and try again ... */ } if (i=NUM_HANDLES) { /* ... before we give up */ ERRMSG(0) "Too many handles open; cannot open \"%s\"", s EEND; } (This code is part of Hugs. It doesn't actually involve ForeignPtrs - Mark Jones had used a ForeignPtr-like mechanism to implement file handles long before I added ForeignPtrs.) -- Alastair Reid Yale Haskell Project Hacker [EMAIL PROTECTED] http://WWW.CS.Yale.EDU/homes/reid-alastair/