Hobby-hacking Eric

2006-02-12

dateparser

Ok, finally fixed the dateparser stuff and understood why it doesn't like those long years. It's nothing to do with haskell, just that System.Time calls some a function from time.h (mktime) to convert dates to number of seconds. Naturally, if the date is something like 105 years ago, then that translates to some really big negative number which is bigger than what you can represent in sizeof(time_h), depending of course on what time_h is defined as on your system. This should be blindingly obvious, of course, but i'm more a high level kind of guy. I hardly even know what a computer is. MaxInt? What the heck is that?

The annoying was trying to figure out how to catch the error gracefully. At first my catches weren't working, and I spent some time puzzling over that, trying to figure out what not. Then I realised that it wasn't the date matcher code itself that was throwing the exception, but the actual attempts to test the date ranges, long after the date has been parsed. So what ended up doing was testing the date range on the current date, just to see if throws an exception or not.
I had to do it in a slighly hacky way, though:

matcher `liftM` now >>=
\x -> if x then return matcher else return matcher
`catchUserError`
\e -> if e == "Time.toClockTime: invalid input"
then error "Can't handle dates that far back!"
else error e


One of the places where haskell laziness is annoying. Normally, i'd just say

matcher `liftM` now
return matcher
`catchUserError`
-- the rest of the code...

and be done with it, but since Haskell is lazy, it never bothers evaluating that, so I had to trick it by using this completely meaningless if.

In other news, on Thu night, I had written a pretty embarassing mail to the Unison list chiming in on Andres Loeh's idea for atomic directories. I basically tried to shed more light on why suc a feature would be useful and point out that it's more important for us darcs users that it be implemented quickly than with a "correct" user interface. Could have said it very simply, but I started going off in random sleep-deprivation-based directions, like saying that maybe if the unison people started to use darcs, they might like it so much that they would feel enough of a sympathy for us that we'd see an implementation the next morning. Ugh. 3-in-the-morning humour. It did elicit a response, however, pointing out places we in the Unison code we should look to in order to implement this. So I think maybe I'll try to get it done. I dunno. Might turn out to be the hard. Too bad unison doesn't have a nice regression testing system like darcs does (does it?). Anyway, so my first step here has been tailorise the unison subversion repo. This will make it easier for me to manage the patches I send in, and it might also be a useful way to show darcs off to the unison crowd. Shrug. Who knows?


3 comments:

Anonymous said...

You can use seq to force evaluation. For example x `seq` y evaluates x and returns y.

kowey said...

Indeed. Using seq lets me write something a bit nicer: matcher `liftM` now >>= \x -> x `seq` return matcher

Can you think of an even better way to express this? I'm thinking maybe something like foo `seqbind` bar = foo >>= \x -> x `seq` bar

But maybe that's redundant with something simpler and more elegant.

kowey said...

Answered my own question: matcher `liftM` now >>= (`seq` return matcher)