Re: [Haskell-cafe] Parsec and Java
There is: http://jparsec.codehaus.org/ HTH, -- OQube < software engineering \ génie logiciel > Arnaud Bailly, Dr. \web> http://www.oqube.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] questions about core
On Mon, Feb 12, 2007 at 04:45:47PM +1100, Matt Roberts wrote: > Hi all, > > I am trying to get a deeper understanding of core's role in GHC and > the compilation of functional languages in general. So far I have > been through > - The hackathon videos, > - "A transformation-based optimiser for Haskell", > - "An External Representation for the GHC Core Language (DRAFT for > GHC5.02)", and > - "Secrets of the Glasgow Haskell Compiler inliner". > > and I am still a bit hazy on a few points: > - What role do *the semantics* of core play (i.e. how and where are > they taken advantage of)? They aren't, at least not directly by the compiler - the semantics are what give people named Simon the courage to implement counterintuitive optimizations without losing sleep. (since they know formally nothing can go wrong) > - Exactly what are the operational and denotational semantics of core? > - The headline reasons (and any other arguments that emerge) for > having core *and* stg as separate definitions. > > I have an intuition on a few of these points, but I would love > something concrete to latch on to. (disclaimer: I am not a GHC hacker, nor have I ever gotten around to actually writing an optimizer.) It's a simple question of expediency and tradeoffs. Core has lots of nice mathematical properties. For instance, Core's call-by-name properties allow the compiler to simply prune unreferenced expressions, without worrying about changing termination behavior. Core expressions can be rearranged by nice pattern matches, and as a strongly typed calculus Core is relatively immune to misoptimization. On the other hand, Core is rather far from the machine, and much is still implicit - invisible and unoptimizable. If GHC only used Core, you would get all the nice large-scale optimizations (fusion comes immediately to mind), but you would pay full price for every forced closure etc - wasted effort could not be optimized away. STG is much closer to the machine. If GHC's desugarer produced STG and Core were removed completely, GHC would still be able to produce nearly perfect code. Every optimization that could be performed at Core, can in principle be performed at STG. In practice things are a bit different. STG, as an impure, strict, untyped langage, is missing the nice properties of Core, and many optimizations that are a no-brainer to write at the Core level, are riddled with side conditions at the lower level. So, to summarize: We have Core because Simon lacks the patience to solve the halting problem and properly perform effects analysis on STG. We have STG because Simon lacks the patience to wait for the 6.6 Simplifier to finish naively graph-reducing every time. (now let's hope that MY intuitions are on the right track!) Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Very fast loops. Now!
I think gcc 4.x have much better optimizations than 3.x since SSA added.I donot know if there are very good IR for functional language optimization. Is it hard for STG language to analysis this kind of code?> go !x !y !i > | i == 10 = printf "%f\n" (x+y) > | otherwise = go (x*y/3) (x*9) (i+1) btw: I always hope to see a C/C++ language compiler writen by haskell.I think it might be much easier to add a new optimization :) 在2007-02-11,Rafael Almeida <[EMAIL PROTECTED]> 写道: On 2/10/07, Donald Bruce Stewart <[EMAIL PROTECTED]> wrote: > The following C program was described on #haskell > > #include > > int main() > { > double x = 1.0/3.0; > double y = 3.0; > int i = 1; > for (; i<=10; i++) { > x = x*y/3.0; > y = x*9.0; > } > printf("%f\n", x+y); > } > > > Which was translated to the following Haskell: > > {-# OPTIONS -fexcess-precision #-} > > import Text.Printf > > main = go (1/3) 3 1 > > go :: Double -> Double -> Int -> IO () > go !x !y !i > | i == 10 = printf "%f\n" (x+y) > | otherwise = go (x*y/3) (x*9) (i+1) I've compiled the exactly same programs, passing the same parameters to the compiler as you did, but I've got a very different result: $ ghc -O -fexcess-precision -fbang-patterns -optc-O3 -optc-ffast-math\ -optc-mfpmath=sse -optc-msse2 loop.hs -o haskell_loop $ time ./haskell_loop 3.3335 real 0m14.092s user 0m14.057s sys 0m0.036s $ ghc --version The Glorious Glasgow Haskell Compilation System, version 6.6 While the haskell program took so long, the C program went really faster than the haskell version: $ gcc -O3 -ffast-math -mfpmath=sse -msse2 -std=c99 loop.c -o c_loop $ time ./c_loop 3.33 real 0m0.001s user 0m0.000s sys 0m0.000s $ gcc --version gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) I'm using debian etch (linux), my processor is a pentium 4 3.0ghz, which has sse and sse2 (or at least /proc/cpuinfo says so). As for memory, it probably doesn't matter much in this test, but I have 512mB of ram. In a similar thread that was posted at comp.lang.functional (it was actually regarding ocaml vs C++, you can find it on google groups at http://tinyurl.com/292ps6 ) the same kind of discrepancy occurred. Showing that this kind of benchmarking is usually not very accurate or, at least, that my processor is not well suited for functional languages :P. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] questions about core
Hi all, I am trying to get a deeper understanding of core's role in GHC and the compilation of functional languages in general. So far I have been through - The hackathon videos, - "A transformation-based optimiser for Haskell", - "An External Representation for the GHC Core Language (DRAFT for GHC5.02)", and - "Secrets of the Glasgow Haskell Compiler inliner". and I am still a bit hazy on a few points: - What role do *the semantics* of core play (i.e. how and where are they taken advantage of)? - Exactly what are the operational and denotational semantics of core? - The headline reasons (and any other arguments that emerge) for having core *and* stg as separate definitions. I have an intuition on a few of these points, but I would love something concrete to latch on to. Thanks Matt R ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Genuine Eratosthenes sieve [Was: Optimization fun]
It has been already remarked that any algorithm of finding prime numbers that uses division or `mod` operations cannot be called (Eratosthenes) sieve. The insight of Eratosthenes is finding primes without resorting to division or multiplication. In his time, doing either of those operations was quite expensive (especially given the way numbers were written in Ancient Greece). Thus Eratosthenes devised one of the early examples of trading space for time. These days it's the other way around: it is far easier for a modern CPU to divide numbers than to access memory. So, the original algorithm is of historical interest it seems. Still, in the interest of purity, here it is, in Haskell. As the original Eratosthenes sieve, this algorithm uses only successor and predecessor operations. -- repl_every_n n l replaces every (n+1)-th element in a list (_:l) with 0 {- The following leaks memory! repl_every_n :: Int -> [Int] -> [Int] repl_every_n n l = case splitAt n l of (l1,_:l2) -> l1 ++ 0:(repl_every_n n l2) -} -- But this seems to run in constant space... repl_every_n :: Int -> [Int] -> [Int] repl_every_n n l = repl_every_n' n l where repl_every_n' 0 (_:t) = 0: repl_every_n n t repl_every_n' i (h:t) = h: repl_every_n' (pred i) t primes = 2:(loop [3,5..]) where loop l = case dropWhile (==0) l of (h:t) -> h:(loop (repl_every_n (pred h) t)) main = putStrLn $ "Last 10 primes less than 10: " ++ show (take 10 $ reverse $ takeWhile (< 10) primes) {- Last 10 primes less than 1000: [997,991,983,977,971,967,953,947,941,937] -} {- Last 10 primes less than 1: [9973,9967,9949,9941,9931,9929,9923,9907,9901,9887] -} {- Last 10 primes less than 10: [1,99989,99971,99961,99929,99923,99907,99901,99881,99877] -} ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Optimization fun
I wrote: > primes :: [Int] > primes = 2 : filter isPrime [3,5..] where > f x p r = x < p*p || mod x p /= 0 && r > isPrime x = foldr (f x) True primes Creighton Hogg wrote: > This looks really slick to me, thanks. > So if I understand correctly, the main thing that makes this work is that > &&'ing the test with the accumulator r will make it bail out of the fold > as > soon as one of the two tests is failed because the result must be False? Yes. Look at the definition of %% and ||: True && x = x False && _ = False True || _ = True False || x = x The second argument of && or || won't be evaluated if the first determines the result. And this brings you back to the point made by Lennart and others about why foldl is the wrong choice: foldl won't allow you to take advantage of this short-circuiting. Write out a few steps of each type of fold if you don't understand why. Note, I wouldn't call r an accumulator: it's just the rest of the fold (which, as you've pointed out, only needs to be evaluated if you don't already know the result). Since writing the above, I've realised that the second argument of the foldr most certainly shouldn't be True. One might be able to argue that False would be more correct, but really it's irrelevant since we know we'll never reach the end of the list of primes. What I found most surprising was that replacing True with undefined made the calculation about 10% faster (GHC 6.4.2, amd64): > primes :: [Int] > primes = 2 : filter isPrime [3,5..] where > f x p r = x < p*p || mod x p /= 0 && r > isPrime x = foldr (f x) undefined primes Comparing this to DavidA's solution: At least on my platform, testing (x < p*p) is significantly quicker than using quotRem/divMod. I suspect quotRem actually requires the division to be performed twice, and multiplication is faster than division. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Foldr tutorial, Inspired by Getting a Fix from a Fold
I hope the following doesn't come across as condescending... The recent issue of The Monad Reader has generated some excitement, mostly to do with the time travel article. I, however, would like to discuss a simpler solution to implementing dropWhile with foldr, which is discussed in the first article of TMR. When I was taught about folds, I was told that foldr starts at the end of the list and then builds up the result from there. But this turns out to be an unhelpful way of thinking. It's better to say foldr starts at the beginning of the list, just like foldl. But how does this work? To see, we'll start by implementing a simpler function than dropWhile, one which determines whether we should cons an element onto a list or just return the list. dropHead p x xs = if p x then xs else x:xs Note that I've funnily given a separate arg to the head of the list and to its tail. That's not a typo and later we will see why. Now let's apply dropHead to each element of the list [1, 2, 3, 4, 5]: map (dropHead p) [1, 2, 3, 4 ,5] => [dropHead p 1, dropHead p 2, dropHead p 3, dropHead p 4, dropHead p 5] Now we need to figure out where to get the second argument for each of the dropHead applications. I know! If a call to dropHead comes before another call to dropHead, we'll pass the result of the second call as the second arg of the first. And if there are no calls after a call to dropHead, we'll pass our base case as the second arg to that call. Let's have a look: threadResults basec [] = basec threadResults basec [f:fs] = f $ threadResults basec fs threadResults [] [dropHead p 1 ...] = dropHead p 1 $ dropHead p 2 $ dropHead p 3 $ dropHead p 4 $ dropHead p 5 [] Let's see it in action! First let's let our predicate determine whether a value is less than three. dropHead (< 3) 5 [] = if (< 3) 5 then [] else 5:[] => [5] dropHead (< 3) 4 [5] = if (< 3) 4 then [5] else 4:[5] => [4, 5] dropHead (< 3) 3 [4, 5] = if (< 3) 3 then [4, 5] else 3:[4, 5] => [3, 4, 5] dropHead (< 3) 2 [3, 4, 5] = if (< 3) 2 then [3, 4, 5] else 2:[3, 4, 5] => [3, 4, 5] dropHead (< 3) 1 [3, 4, 5] = if (< 3) 1 then [3, 4, 5] else 1:[3, 4, 5] => [3, 4, 5] => [3, 4, 5] Do you now see how foldr works? It starts at the beginning of the list and applies the function you gave it to the first element of the list. Then to get the second argument of the first call, it applies your function to the second element of the list and passes the result of that to the first call. In other words, it /recurs/ on the next element of the list. When we finally get to the end, the base case is passed to the final call of your function and it returns, and all the previous calls return building their results from the calls after. So in other words to implement dropWhile with foldr merely requires: dropHead p x xs = if p x then xs else x:xs dropWhile p l = foldr (dropHead p) [] l Or even simpler: dropWhile p = foldr (\x l' -> if p x then l' else x:l') [] take 3 $ dropWhile (< 5) [1..] => [5, 6, 7] No abtruse machinery required! __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Optimization fun
On 2/10/07, Matthew Brecknell <[EMAIL PROTECTED]> wrote: Rafael Almeida said: > I've always found the following definition of the sieve of eratosthenes > the clearest definition one could write: > > sieve [] = [] > sieve (x:xs) = x : sieve [y | y <- xs, y `mod` x /= 0] > > It doesn't perform better than Augustsson's solution. It does fairly > worse, actually, but it performs way better than Hogg's 13s algorithm. > It took around 0.1s on my machine. Interesting. I found the sieve to be somewhere around the 13s mark, while Lennart's solution was about 0.15s. But that may just be because I haven't yet made the jump from GHC 6.4.2 to 6.6... I also found that a handcrafted loop-fusion reduced Lennart's solution to 0.08s: primes :: [Int] primes = 2 : filter isPrime [3,5..] where f x p r = x < p*p || mod x p /= 0 && r isPrime x = foldr (f x) True primes This looks really slick to me, thanks. So if I understand correctly, the main thing that makes this work is that &&'ing the test with the accumulator r will make it bail out of the fold as soon as one of the two tests is failed because the result must be False? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC throws IOError on Win32 when there is no console
Hi Paul, Can I have your code that doesn't work? I want to fiddle with it a bit. Thanks -John On 2/12/07, Paul Moore <[EMAIL PROTECTED]> wrote: On 09/02/07, Paul Moore <[EMAIL PROTECTED]> wrote: > It probably wouldn't be hard to write a reasonably general wrapper for > this, but it's a bit late now so I'll leave that as an exercise :-) Sigh. I tried to set this up (using a little external C routine to do the API grunt work) and it doesn't seem to work as I expect. Maybe the C/GHC runtimes do something more complex than just using the API standard handles, maybe I coded something wrong. In theory, this should work. In practice, Haskell may benefit from an equivalent of the C freopen() function (from stdio), which deals correctly with the internals of handles... Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Optimization fun
"Rafael Almeida" <[EMAIL PROTECTED]> writes: > I've always found the following definition of the sieve of eratosthenes > the clearest definition one could write: > > sieve [] = [] > sieve (x:xs) = x : sieve [y | y <- xs, y `mod` x /= 0] > It doesn't perform better than Augustsson's solution. It does fairly > worse, actually, but it performs way better than Hogg's 13s algorithm. > It took around 0.1s on my machine. > > You should call the function like this > > sieve [2..n] > > where n is to what number you want to calculate the sieve. I could also > have used filter instead of the list comprehension. What you have here, is not a sieve (in my opinion) as any implementation that uses `mod`. The characteristics of a sieve is, that it uses the already found primes to generate a list of non-primes that is then removed from a list of candiates for primeness. The salient point is, that there should be no test divisions, but rather only comparisons. In the imperative version the comparisons are implicit (in the process of marking the array positions), but there are no test divisions. A real sieve should look like this (IMHO) http://www.etc-network.de/blog/mel/programming/how-to-spend-midnight.html#how-to-spend-midnight This is my implementation, please, forgive my shameless self-advertisment :-). Regards -- Markus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Optimization fun
Yes, and that's pretty much what my version does (and what the original tried to do?). On Feb 11, 2007, at 20:14 , DavidA wrote: If you want it fast, don't use a sieve method at all (or a wheel method) - use trial division: primes = 2 : [p | p <- [3,5..], trialDivision primes p] trialDivision (p:ps) n | r == 0= False | q < p = True | otherwise = trialDivision ps n where (q,r) = n `quotRem` p trialDivision [] _ = True ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Very fast loops. Now!
Donald Bruce Stewart wrote: The following C program was described on #haskell #include int main() { double x = 1.0/3.0; double y = 3.0; int i= 1; for (; i<=10; i++) { x = x*y/3.0; y = x*9.0; } printf("%f\n", x+y); } Which was translated to the following Haskell: {-# OPTIONS -fexcess-precision #-} import Text.Printf main = go (1/3) 3 1 go :: Double -> Double -> Int -> IO () go !x !y !i | i == 10 = printf "%f\n" (x+y) | otherwise = go (x*y/3) (x*9) (i+1) Do the two programs implement the same algorithm? The C program updates x and y in sequence. The Haskell program updates x and y in parallel and can be easier for the compiler to optimize. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Optimization fun
If you want it fast, don't use a sieve method at all (or a wheel method) - use trial division: primes = 2 : [p | p <- [3,5..], trialDivision primes p] trialDivision (p:ps) n | r == 0= False | q < p = True | otherwise = trialDivision ps n where (q,r) = n `quotRem` p trialDivision [] _ = True ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC throws IOError on Win32 when there is no console
On Sun, 2007-02-11 at 17:18 +, Neil Mitchell wrote: > Hi > > > Good point. Perhaps you can persuade the people who look after GHC on > > win32 to have it use the Windows debug log service for exception > > messages like that when there's no GUI available. Of course if you can > > code up and submit such a patch yourself then even better. > > Does anyone read that? Wouldn't a message box be better? The point would be only to do that when there is no GUI available, eg when running as a service. Otherwise, the message box is indeed better. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC throws IOError on Win32 when there is no console
Hi Good point. Perhaps you can persuade the people who look after GHC on win32 to have it use the Windows debug log service for exception messages like that when there's no GUI available. Of course if you can code up and submit such a patch yourself then even better. Does anyone read that? Wouldn't a message box be better? Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC throws IOError on Win32 when there is no console
On Sat, 2007-02-10 at 23:46 +1100, John Ky wrote: > Hi Duncan, > > Thanks for your comments. In the context of a haskell process running > as a Windows service, a message box is useless, because Haskell > services do not have a GUI and cannot interact with the desktop. Good point. Perhaps you can persuade the people who look after GHC on win32 to have it use the Windows debug log service for exception messages like that when there's no GUI available. Of course if you can code up and submit such a patch yourself then even better. Duncan > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] FFI basics
Hello Yitzchak, Sunday, February 11, 2007, 4:14:39 AM, you wrote: > when I have time. What Bulat wrote is in my opinion > _exactly_ what is needed. i has a pedagogical talent :D searching for Haskell teacher position :))) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC throws IOError on Win32 when there is no console
On 09/02/07, Paul Moore <[EMAIL PROTECTED]> wrote: It probably wouldn't be hard to write a reasonably general wrapper for this, but it's a bit late now so I'll leave that as an exercise :-) Sigh. I tried to set this up (using a little external C routine to do the API grunt work) and it doesn't seem to work as I expect. Maybe the C/GHC runtimes do something more complex than just using the API standard handles, maybe I coded something wrong. In theory, this should work. In practice, Haskell may benefit from an equivalent of the C freopen() function (from stdio), which deals correctly with the internals of handles... Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lambada and connecting Haskell to a Weblogic server
Yep, don't have access to the Weblogic server. I'm re-evaluating my options, though, since I'm lazy by nature. On Feb 11, 2007, at 12:30 PM, Neil Bartlett wrote: Joel, Implementing Java RMI in Haskell sounds like a nightmare. Why not use HTTP? You could easily write a wrapper Servlet that speaks XML or JSON over HTTP, and deploy that to the Weblogic server. Unless you don't have permission to deploy anything to that server for whatever reason. -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lambada and connecting Haskell to a Weblogic server
Joel, Implementing Java RMI in Haskell sounds like a nightmare. Why not use HTTP? You could easily write a wrapper Servlet that speaks XML or JSON over HTTP, and deploy that to the Weblogic server. Unless you don't have permission to deploy anything to that server for whatever reason. Alternatively, how about AMQP ;-) Regards Neil On 11 Feb 2007, at 01:50, Joel Reymont wrote: Folks, Where can I find Lambada these days and would it be of any use to me in trying to connect to a Weblogic server? To make the long story short, my broker's Java software connects to a remote Weblogic server and I would like to do the same. I suppose this would require me to implement Java RMI in Haskell which is non- trivial. I wonder if it would be easier for me to implement a Java server that talks to Weblogic and then connect to that server. What do you think? Thanks, Joel -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What's wrong with "cgi-undecidable"?
On Sun, Feb 11, 2007 at 09:11:59AM +0100, Bjorn Bringert wrote: > Yeah, that would make specifying dependencies a bit of a drag. I > think I'll just rerelease all the packages as version 3000.0.0 or > something. Who cares if the version numbers look silly? The Debian Project uses standardized version numbers, and has a special field "epoch" which is incremented whenever the version numbers change; so for instance 2:1.0 comes *after* 20060413. perhaps this could be adapted in the context of cabal? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What's wrong with "cgi-undecidable"?
On Feb 11, 2007, at 0:12 , Robin Green wrote: On Sat, 10 Feb 2007 23:37:04 +0100 Bjorn Bringert <[EMAIL PROTECTED]> wrote: I've also recently changed the version number scheme on most of the packages I maintain (which includes most of the packages required by Hope) from a date-based one to a major.minor scheme. This has the unfortunate side-effect of making newer versions have smaller version numbers than older ones, but it felt silly to start with a major version number of 2008. That might have been a bad decision. The rPath Linux package management tool, conary, has a nice solution to the problem that software version numbers have inconsistent lexical ordering conventions between projects and sometimes within the same project. It does not compare version numbers at all, and (as far as I can tell) asks the package repository for the most recent package, unless you specify a particular version. Perhaps Cabal could do something similar? Of course, this way you can't express "I want version >= 1.2" which is kind of a bummer. Yeah, that would make specifying dependencies a bit of a drag. I think I'll just rerelease all the packages as version 3000.0.0 or something. Who cares if the version numbers look silly? /Björn___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe