Hobby-hacking Eric


distributed chiming in

It seems that distributed version control has become a somewhat hot topic lately. The latter two posts make the case that being able to work offline is extremely useful, both for road warriors and for users with less than ideal Internet access. Yes, this does seem like a pretty good motivation for distributed version control. Indeed, it was my laptop and my dialup connection (aside from sheer curiosity) that first got me using darcs two years ago. But now I have one of these fancy ADSL connections and a less need to travel or hack offline while doing so. Yet I continue to use and love darcs. I'm sure this is something that bzr, git, mercurial, etc users can attest to: yes, offline versioning is indeed a great feature, but there is something more.

Warning: this is a rather long post. My apologies to planet haskellers and other busy readers.

one mechanism - many benefits

The thing that attracts me to a system like darcs is its conceptual elegance. From one single mechanism, you get the following features for free:
  1. Painless intialisation
  2. Offline versioning
  3. Branching and merging
  4. Easier collaboration with outsiders

These are all the same thing in the darcs world, no fanciness at work whatsoever. I suppose it's not very convincing to sell simplicity in itself, so in the rest of this post, I'm going to explore these four benefits of a distributed model and discuss what their implications might be for you the developer.

Painless initialisation

Getting started is easier because you don't have any central repositories to set up. That might sound awfully petty. After all, setting up a central repository is nothing more than a mkdir and cvs checkout. But it's much more of an inconvenience than you might think.

Setting up a central repository means you have to think in advance about putting your repository in the right place. You can't, for instance, set something up locally, change your mind, deciding that you want a server and switch over instantaneously. You COULD tarball your old repository, move it to the server, and either fiddle with your local configuration or checkout your repository again. But why should you? Why jump through all the hoops? The steps are simple, but they add friction. How many times have you NOT set up a repository for your code because it would have been a pain (a 30 second pain, but a pain nonetheless?). How many times have you put off a repository move because it was a pain? Painless initialisation means two things (1) instant gratification (2) the ability to change your mind. I would argue that such painlessness is crucial because it brings down the barrier of inconvenience to the point where you actually do the things you are supposed to do.

Branching and merging

A well thought out distributed version control system does not need to have a notion of branching and merging? Why? Because a branch can simply exactly the same concept as a repository, as a checkout. No need to learn two sets of concepts of operations or two views of your version control universe. Just think of them as one and the same. Now, you might be worried about say, the redundancy of all this (gee! wouldn't that mean that branches take up a lot of space?)... but eh... details.

For starters, disk space is cheap, at least much cheaper than it was in the past. There might be cases where you are trying to version very large binary files, but for many programming jobs, we are only shuffling text around, so why worry? Besides, branches are supposed to be disposed of one day or another (merged), right? It's not like they're going to be that long lived, otherwise it's just a fork. Moreover, worrying about disk space is the version control system's job, not yours. You could have a VCS that tries very very hard to save space. For example, it could try to use hard links whenever possible, in much the same manner as "snapshot" backup systems. Disk space is not what you the programmer should be worrying about. It's similar to the case being made for having a second or third monitor: programmer time is more valuable than disk space.

Offline versioning

Previous posts have discussed this at length. It's still useful, even if your Internet connection is superb. It's useful because it lets you hold on to things that aren't quite ready for the central repository, but worth versioning until you're more confident about your code.

Collaboration with outsiders

Open source and free software projects thrive on contributions from outsiders. For example, in the past year, 80% of the 360 patches to the darcs repository have come from somebody other than David Roundy, the original author of darcs. I'm cheating a little bit because many of these patches are also from known insiders. Then again, all of the known insiders were outside contributors at some point. The switch from outsider to insider has been for the most part informal: you send enough patches in and people eventually get to know you. And that's it; very little in the way of formal processes.

Outsider collaboration is made easier for two reasons, offline versioning and decentralisation.

By offline versioning, I mean that people can make their modifications locally, retrieve changes from the central repository and still have their modifications intact, versioned and ready to go. Consider a popular project, like the mail client mutt. Some mutt users have patches that are useful for a few people, but not appropriate for the central repository. So they make their changes available in the form of a Unix patch. If you're lucky, the patch applies to the version of mutt that you've downloaded. If you're not so lucky, you've got some cleaning up to do and a new set of patches. I'm not talking about merging or conflict resolution, per se. Assume the conflict resolution requires human intervention. You've fixed things so that it compiles against the new version. What do you do exactly? Make a patch to the patched version? "Update" the original patch so that it works with the new version of the repository? And what about the original author, what does s/he do with your patch? These kinds of things are not so hard in themselves, but they are a major source of friction. They gum up the works of free software development, or any large project, open source or closed.

If you are a project maintainer, having a tool that handles offline versioning means that it is easier for you to accept changes from outsider contributors (zero insertion force - no need to apply patches and re-commit them).

If you a contributor, having an offline versioning tool means that it's easier for you to submit modifications to the project. You don't have manually create patches: you don't have to keep around a clean and working copy of the project, you don't have to worry about where you do your diffs (so that the patch --strip options come out right), you don't have to worry about what happens when the central repository changes and your patch no longer applies. Again, I'm not referring to conflict resolution. If there are conflicts, somebody will have to resolve them; but the resolution and versioning of these conflicts should involve as little bureaucracy as possible. For extra credit points, some version control systems even implement a "send" feature in which you submit your local modifications via email. The maintainers of the repository can then choose to apply the patch at their leisure. These aren't regular Unix diff patches, mind you, they are intelligent patches with all the version-tracking goodness built in.

Offline versioning adds convenience to the mix, a technical benefit. If you flip it around and look at it in terms of distributed controls, you can see some pretty subtle social consequences as well. Since there is no need for a central repository, there is a lot less pressure for the central maintainer to accept patches or reject them outright because you know that the outsider contributors can get along fine with their modifications safely versioned in their local repositories. Worst come to worse, the outside contributors can place their repositories online and have people work from there instead. It sounds like a fork, which sucks... but sometimes, fork happens. Look, sometimes you get forks for differences in opinion, disagreements between developers, or general unpleasantness. But sometimes you get more innocent forks, for example, the main developers suddenly got a new job and is now working 60 hours a week. S/he is still committed to the project, but to be honest s/he hasn't been looking at patches for the last month. No big deal, the rest of us will just be working from this provisional repository until the main developer gets back on his/her feet. There's a social and a technical aspect to forking. Distributed version control greatly simplifies the technical aspect, and that in turn mellows out the social one. Distributed version control means that life goes on.

simplicity and convenience

I'm really only making two points here. Simplicity matters. It reduces the learning curve for newbies and removes the need for experienced users to carry mental baggage around. Convenience matters. It reduces the friction that leads to put off the things you could be doing and it removes some of the technical barriers to wide-ranging collaboration. I could always be mistaken, of course. Perhaps there is some bigger picture, some forest to my trees; and upon discovering said forest I find myself deeply chagrined, getting all worked up over something so silly as patches. But until that time, I will continue to use darcs and love it for how much easier it makes my life.


the Haskell metatutorial

Thanks to ndm for so clearly articulating the idea. Here is my attempt at implementing the Haskell metatutorial. Please add your stuff or even just expand the guide tree. Embrace the explosion of tutorials. Make something useful of it.

15:05:09 < AStorm> YAHT leaps a bit too far for me. I'd like something complete but less steep.
15:05:47 < metaperl> YAHT is probably as good as it gets INHO
15:05:49 < metaperl> IMHO
15:06:01 < uccus> there should be a grant unification project for Haskell tutorials
15:06:02 < metaperl> the "algorithms" book is not bad either
15:06:26 < kowey> uccus: the wikibook attempts to remix heavily
15:06:28 < uccus> *grand [blushes]
15:07:01 < kowey> we've got yaht, write yourself a scheme, jeff newbern's stuff, some original content, all mashed up and duct-taped together
15:07:03 < ndm> what i would like is a meta-tutorial
15:07:14 < ndm> a list of questions about haskell, what does this do, do you understand this etc
15:07:26 < ndm> and if you say no, it points you at a tutorial which explains it
15:07:28 < uccus> well, mashed up and duct-taped is not good
15:07:41 < ndm> is there a tutorial on pattern matching, for instance?
15:07:44 < uccus> aah. yes. I agree with ndm
15:07:47 < kowey> we could use some heavy editing
15:07:48 < ndm> which covers ~, !, @ etc
15:08:12 < kowey> right, me too... it's like the malcolm gladwell stuff
15:08:17 < uccus> the wikibook can do that
15:08:31 < kowey> many "right" flavours of coffee, pepsi; extra-chunky tomato sauce, etc
15:08:40 < uccus> it's divided into sections... they can contain links to complete tutorials
15:08:59 < uccus> everyone has a different style of tutoring you know...
15:09:05 < kowey> i agree
15:09:16 < kowey> the wikibook right now is newbie-oriented
15:09:28 < kowey> but we could steer it towards choose-your-own-adventureness
15:09:43 < uccus> kowey: the wikibook right now has different steams for newbie/advanced(?)
15:09:45 < kowey> comments on the discussion page on how we could implement this would be quite welcome
15:09:55 < kowey> we have two tracks, newbie and advanced
15:10:16 < kowey> although the advanced track assumes you've basically just gotten through the newbie track... it tries to be a friendly "advanced"
15:10:19 < uccus> yes, but shouldn't there be more?
15:10:39 < uccus> tracks?
15:10:41 < kowey> well, it's got two tracks in terms of material, one track in terms of style
15:11:04 < kowey> what ndm is talking about is having multiple tracks in terms of style (well... style, level)
15:11:10 < uccus> I mean, the grand Haskell wikibook should contain things that are really advanced
15:11:25 < uccus> like tutes for gtk2hs...
15:11:37 < ndm> kowey: i more meant accepting there will be loads of tutorials, but trying to point people at those which will teach them something new
15:11:42 < uccus> *that* should be called advanced
15:11:44 < kowey> i tend to suspect that's more the Haskell wiki's job
15:12:13 < kowey> although there is http://en.wikibooks.org/wiki/Haskell/GUI
15:13:07 < uccus> aaah. thanks kowey. that's enough I think.
15:13:33 < kowey> ndm: i think we're saying the same thing, although i'm speaking horribly imprecisely



I wish unravelling code was easier. For me, coming to grips with a large software project often consists of undoing bundles of yarn, the big chain, multiple dependencies coming in, multi dependees going out. You want to find out where function foo is used. Well, it turns out that it's used by bar, so now you have to find out where bar is used, and oh it's used by quux... and... oh boy.

I wish there was some tool that would let me start from the center of the big old yarn ball and swim out to the surface. I'm not sure how something like this would work either. Ultimately, all the low-level stuff is used in your main, right? So how can you display this kind of information without just overwhelming the user?

Ctags/Hasktags aren't too useful here. They solve the opposite the problem, in which you've got some top level function and you want to drill down to the guts. Graphviz-ing your modules just gives you a thicket, something to marvel at, but not a great source of insight. Dep trees in some hypothetical browser don't sound that useful either (sigh, click the triangle, expand the subtree, whoah! too much! collapse! collapse!).

The mental image I get is that you run it on your code:
unravel Population.applyToPop *.lhs *.hs
and you'd get a browseable, filtered view of the source code, the relevant bits highlighted, useful links in the right places, but not so many that you feel overwhelmed. I want it to be a standalone tool (like a graphical diff utility), something I can run without having to learn how to use your favourite IDE. Likewise, I want it to be quick and easy (again, the standard for ease being a graphical diff). I don't want to set up a project folder or whatever just so I can run the tool.

This is one annoying aspect of being a user, hell a consumer of any kind. I know I want something, but I don't know exactly what, except that I'd probably recognise it when I see it. The ideas in my head are muddled. If somebody sat me down for a user-interview, I'd just sort of ramble on incoherently for 10 minutes, get confused and wander off. Dear whoever, please build me an unraveller. Think like an Apple UI engineer here. Build the tool from user-experience-in, not from functionality-out. Don't listen to my precise demands, because I don't really know what I want. Just help me understand this code.

Anybody know what it is I'm looking for? (If you do have such a tool, a good exercise would be to run it on darcs. Can it help you figure out what a Slurpy is? How about a Population?)


Denotational semantics

Apfelmus from IRC just wrote what looks like a very nice chapter on denotational semantics. I am reading it now and learning lots. Why not check it out and post comments on the talk page? I'm sure he'll appreciate any comments the Haskell community might have, or anyone with an interest for that matter.

Thanks, afpelmus; what a great Christmas present!


It's alive!

Hier sur #haskell.fr, on était plus que 2 personnes pour la première fois. Grace aux iniatives de Nanar et cie, il est possible qu'un veritable communauté francophone d'Haskelliens (?) verra le jour.

Sorry for that attempt at parlezing français. I'm pleased to see that the French Haskell community has now increased two-fold to an amazing four people (on the #haskell.fr at least). Venez nombreux or something. It'll be fun. Thanks to Nanar for kickstarting things with a wiki/mailing list/channel creation initative.


rewriting PLEAC Haskell?

One complaint I have heard about the Haskell cookbook is that it is rather unidiomatic and thus not very helpful for people trying to learn Haskell. For example, one particularly shocking thing the implementation does is to shadow (.) operator to make more "object-like": o . f = f o (reverse dollar? euro?). This leads to snippets of code which, as one of the wikibook commentors put it, are barely recognisable as Haskell:
s''' = s1.split " ".reverse.join " "

PLEAC Haskell in its present form is not very suitable for educational purposes, but what if the Haskell community ran through and cleaned it up? Only the first two chapters are implemented anyway, so it doesn't seem to be all that much; the only substantial thing to rewrite perhaps being in soundex code. I personally cannot invest any time in this, being already behind in other projects like darcs and wxhaskell, but it might be a fun project for Haskell enthusiasts, or even yellow-belt Haskellers trying to come to grips with the language.

If interested, you should probably subscribe to their mailing list and maybe bounce around some ideas on the Haskell café. Another thing to consider is contacting the original author Yoann. It would be good to get him on board, maybe with a little gentle persuasion. I mean, he probably thought it was a good idea to make the language more recognisable to newcomers. Nice thought... but maybe he would now agree that newbies would be better off with more idiomatic Haskell.


wxhaskell unicode testing

One of my reponsabilities is to make sure that the wxhaskell Unicode stuff is working. I'm still not too sure what the best way to go about this is. I suppose that any such test would require a majour eyeball component, although it would probably be prudent to add a bit of automation and randomness to things. Here's my first attempt anyway:

I have a small UTF-8 text file with text in a bunch of different scripts. Combined some code from one of the haskell mailing lists to read a file into [Word8] with some an UTF8 encoder/decoder from darcs (this particular code claims to be from the Haskell i18n working group and is BSD licensed). I read the file, break it down into lines and display a copy of each widget for each line in the file. I've only got checkboxes, haven't figured out how I want to go through all the widgets yet.


haskell / vim indentation

Thanks to motormean for his (or her) haskell indentation vim script. It solved that annoying problem with birdtracks being indented. Now I can break up a line without having to deal with the ">". No word yet on how this words with latex-style literate haskell, but I am grateful already.


yaht now pure gfdl

Oops. I realised a couple of weeks ago that dual licensing Hal/GFDL on the PDF meant that I couldn't back-propagate wikibook patches into the LaTeX version. So now the PDF is GFDL only. Nice and simple.

(I dropped Hal an FYI and invited him to yell. Since it's _already_ GFDL anyway, I saw no reason that he would mind, which he does not seem to, cf no yelling)


yaht on darcs.haskell.org

Going to try a little experiment here. Wikis are great, rah rah instant collaboration and all... but gee LaTeX just seems so much better for putting together nice looking documents. Wouldn't be nice if one the community's best free Haskell tutorials were available under darcs, its LaTeX guts exposed to the world?

Now you can darcs get http://darcs.haskell.org/yaht and send your patches to me. I'm essentially forking YAHT here: we've got the yaht-wikibook on one hand, and yaht-darcs on another; with eric occasionally scurrying around to hand-migrate patches from one tine to the other. yaht-wikibook is GFDL. yaht-darcs is dual-licensed Hal copyright-GFDL. Oh and btw, update your links. The new PDF is also on darcs.haskell.org: http://darcs.haskell.org/yaht/yaht.pdf.

WikiYaht or DarcsYaht, who's gonna win? (Or maybe our dreams of a darcs-based latex-friendly wiki will come true or something)


wxhaskell on darcs.haskell.org

Well, it's official. The wxHaskell revival is now underway. No promises on when the next release is coming out, but getting a binary release out the door is the first thing we're aiming for.

We'll now be using a darcs repository as our main development:
darcs get http://darcs.haskell.org/wxhaskell

We retain sourceforge for all our other interactions (bug tracking, file distribution, etc). We're adopting a darcs-project model of development -- gee, I wonder why -- in that mostly everything is darcs sent to the mailing list for community review and one person (that would be me) gets the job of pushing the patches in. My policy is that if one of the core wxhaskell team says it goes in, it goes in.

My personal objectives are to get the build system working better and wring out the Unicode stuff. Shelarchy has a patch which makes it compile with ghc 6.6, but does automatic install of wxcore... I'd prefer to have it so that you have a little more control over the process: make; make install; make wx; make wx-install). Hopefully, separating the wxcore and wx build stuff will make Cabalisation easier. If we don't know how to cabalise wxcore, at least we should be able to cabalise wx. As for the Unicode stuff... well, I haven't thought too hard about it yet. Will likely involve some way of testing things out thoroughly. Any thoughts on the matter?


yaht (badly) imported

YAHT is now a part of the wikibook. It took me a day of scripting, plus a couple hours here and there. I'm pretty embarassed about the way I did it, mostly a bunch of dumb regular expressions (Text.Regex) mixed in with a hacked-up versiono of lhs2tex. Lhs2TeX only has a pseudo TeX parser, which is better than anything I could have come up with in a short time. The lack of an abstract syntax tree was a bit annoying, but then I just recursively ran the texparser on any strings that were in environments, and things were more or less ok. Two things I really handled badly were math (you can see where my regexps go horribly awry) and links (I could have come up with better smarts for this...) (*).

There'll be some cleaning up to do, but as far as I know, it's all there. Let the great Haskell Remix begin!

(*) I call the result "YahtSee", short for "Yaht converter"


yaht sources!

Many thanks to Hal Daume III for the tex sources to Yet Another Haskell Tutorial. As soon as I have time to work on the import, the Haskell wikibook will include the entirety of YAHT. We'll do this in two phases, I think. First I'll create a subpage of the wikibook containing the original YAHT. People can continue to use and modify that version indefinitely, because hey, it's pretty damn good. The second phase will consist of us wikibookians mashing up our stuff with YAHT stuff. Lot's of borrowing, moving, deleting and debating. It might come out great, best of both worlds, or it might just end up being horribly clumsy, but it'll be a worthwhile experiment!


getting things done with mutt

Edit 2007-10-29: a reader asked me to add the gtd and mutt tags to this article. Thought I might take advantage of the situation to tidy up the article a little.

You've probably heard about Getting Things Done (GTD) and lifehacks by now. If not, it provides a simple, but non-obvious algorithm for human beings to stay on top of things in a stress-free and effortless manner. My implementation of the GTD spec is working pretty well, but it has one huge, gaping hole: e-mail. The following is a collection ideas for plugging the hole and adapting my favourite mail client, mutt, to be more GTD friendly.

basic next action labeling (X-Label)

My mail processing workflow is GTD inspired -- interestingly queues work better for email whereas stacks work better for real life -- but one major flaw is that when I save a message to =ACTION. The problem is that I was using paper to write my actions down. Paper's great, but it's not very convenient for something which is inherently computer-based (it means dragging my notebook out of my backpack, for example). What I needed was some way to associate email messages with actions.

Fortunately, a fellow mutt user has made a small patch to add an onboard X-Label editor to mutt. This is almost perfect for annotating messages with Next Actions and Waiting Fors. It does not compile against the mutt [1.5.13] that's in MacPorts, but I have updated the patch and Portfile so that it does. I will put it on the web if somebody's interested.

The following should go into your muttrc, so that to set a next-action, you simply hit 'y':

bind pager y edit-label
bind index y edit-label

To make this more useful, I also add the following white on red highlighting so that the next action is the most visible part of the message:

color header white red "^X-Label:"

Filing to =ACTION (user-input)

I currently have the following set in my muttrc so that Ctrl-A saves the current message in =ACTION and Ctrl-W saves it in =WAITING (=WAITING is problematic, a bit of a black hole).
macro index \Ca "<save-message>=ACTION"
macro pager \Ca "<save-message>=ACTION"
macro index \Cw "<save-message>=WAITING"
macro pager \Cw "<save-message>=WAITING"

What I would like to do is script it just a little bit more so that Ctrl-a asks me what the next action is, and then saves it in =ACTION. What I need is a mutt feature (maybe it already exists) which I call <user-input> (which basically means, wait for the user to type something and hit enter). Then I can extend my macros like so (pager ommited):
macro index \Ca "<edit-label><user-input><save-message>=ACTION"
macro index \Cw "<edit-label>WF: <user-input><save-message>=WAITING"

I guess saving a couple of keystrokes isn't that big a deal. I could just have a workflow where first I hit 'y', plug in my next action, and then I hit 'Ctrl-a' (this is what I do now). But it would be nice if this was enforced by my keybindings. Note that in order for this not to be horribly irritating, the macro system should stop processing the macro if the user hits 'Ctrl-c'. In other words, if I change my mind about setting a next action, it should just stop there and not file my mail for me automatically (which would mean I'd have to fish it out, etc)

Next Action counter

One thing I would like to have whenever I'm looking at my mail is to have a small, discreet counter telling me how many next actions and waiting fors I have. You know that bar on the bottom of the screen in mutt? That's where I'd put it, on the right. ----- Actions: 9 WF: 15 ----. A little reminder like that would be great!

Next Action preview

Another thing which might be useful is to be able to 'preview' a message, but only showing its next action. When i'm in index mode of mutt, for example, below that bar on the bottom of the screen, I would like to have one line showing me the value of the X-Label.

that's all!

That's all I have for now. Please comment if you have any other ideas or mutt-gtd tips.


back from Haskell Workshop / ICFP

Got back yesterday early afternoon. Have spent the weekend just being a lazy slob, something I tend to do right after a trip.

But need to get things into gear.

Still need to writeup the patch theory 2.0 discussion we had, mostly droundy, Igloo, lispy and some strategic insight from kosmikus (and me furiously writing notes on the laptop and asking questions of the style "I clearly have not been listening to the last 10 minutes of this discussion". You know the kind...

There be patches in queue too.

Other than that, I have bought myself my first laptop, an ultimate white Macbook. Was relieved that compiling darcs on it wasn't very hard (need to toss '-package mtl' into the Makefile, as Will on the mailing list found out). I was starting to find the lab's iBook G3 a little slow for my needs (mostly [re-]compiling darcs). Am installing Debian on a Parallels virtual machine as we speak. Plan to do Windows XP as well, although I am a bit worried about it not being fast enough for me to compile and play around with darcs. Other than that, the main blocker is that I don't actually own any Windows license keys. Perhaps Micrsoft would be generous enough to donate a couple of keys to the project? It might help us debug stuff, after all.

Actually what would be better is if some Windows gurus decided to join the project. Come on, Windows hackers, you want to be a darcs developer too and you know it!

Gah. Planet Haskell. It's so embarassing to think that people are actually reading this. I'm not sure what makes me more self-conscious, people looking at my code (GPL forever... or at least until I find myself employed by somebody that objects to it), or my English (I'm an almost native speaker, so that's not the problem). When I read myself, I hear a mixture of valley girl blended with remnants of my choppy Malaysian accent and sprinkled with a good dose of whining and uninteresting detail (today I ate cereal) for good measure. Sigh... hit that Publish button eric, and get it over with.



It's official. Today I begin my role as darcs unstable maintainer, thus switching from hobby-hacking to hobby-patch-and-bug-tracker-watching. We've have been planning this for some time now, as Juliusz has some hefty time constraints to deal with.

I'm somewhat worried about this, and would rather somebody more competent did the job, because I don't exactly have the same foresight or discipline in thinking about the consequences of patches. I'm really more an incremental improvements, add a small feature kind of guy. Oh well. No better way to learn, I suppose. Plus I get to feel all important and stuff ;-) But maybe now we should have a motto for the unstable branch, something like, "darcs unstable... and we mean it!"

Now need to become more organised so that I can stay responsive, while keeping this, the wikibook and the wxhaskell stuff a fun hobby, something to take my mind off but not get in the way of the thesis.


Does Haskell hurt your brain?

Feel free to bitch about Haskell in the comments! I'm interested to see how one should go about writing the How to read Haskell tutorial, as well as the Haskell wikibook.

The tutorial is aimed at people who want to understand some piece of Haskell code they encounter, or who like to learn by example (and quickly find themselves lost). The wikibook is more aimed at people who are new to programming and who are said to have an easier time picking up Haskell than their l33t hacker friends (you know, not so much unlearning to do). Speaking of l33t hackers, maybe this would be a good chance to point out Haskell for C programmers...

Anyway, yeah so, if you've been turned off by Haskell because it's hard, weird or painful, let me know. Note that if I receive any comments at all, I'm somewhat expecting them to be about IO and monads. Those comments are welcome too, although I would like them better if you followed up with any insights about what make them hard for you to understand. Otherwise, what I would most like to see are the complaints about reading and understanding Haskell code.


eric shuts up at last (and dreams of tidyness)

Alright, I'm going to put my foot down and force myself to take the thesis more seriously. This means you should be
  1. seeing me posting only before my 22:00 bedtime (eh... oops)
  2. not be hearing from me as much (yay!).

reorganising our stuff

I wonder what it would look like if somebody got down to it and started tidying up the darcs hierarchy... I think I've talked about this, like, a year ago, but somebody on the channel (wisely) said that we should wait until the conflictors stuff is finished... Hmm... but hypothetically, what would it look like? Maybe something like this?

Darcs.Command (formerly DarcsCommand)
Darcs.Repository (as in Darcs/Repository.lhs)

Darcs.Support sounds pretty stupid, but I don't know what else I'd call it. Basically for stuff which supports the Darcs.Command stuff (maybe it'd just go under Darcs, as in, Darcs.Arguments). This isn't the only way to do it, of course. Somebody else might have a better idea... but whatever way we choose, it'll be a lot nicer than what we have now. A bit more approachable, anyway.

wxhaskell / wxC

I have a new project! (Oh no). So one day, sort of randomly, J.O'D on haskell-cafe takes the intiative to a start a wxhaskell revival process, and naturally enough, I volunteered to help out. I have now been assigned the task of making sure the Unicode stuff works (which I'm interpreting mostly as figure out how to write a semi-automated eyeball test suite).

Of course, one of the first things I ask for is for wxhaskell to switch to darcs. This project has been first-hand experience for me why a distributed version control system is so useful: it keeps the bit-rot away. Darcs's patch-oriented nature would have allowed us to keep a Unicode fork of wxhaskell alive whilst waiting for the official maintainers to find the time to bring the project back to life. You can't blame them... people are busy, right? The situation we faced with wxhaskell was one where Unix patch was piling on top of Unix patch; it was getting a little messy and annoying. This was exactly the kind of situation where easy forking and easy healing can keep a niche project alive.

I feel kinda silly. I've apparently had a tailorised darcs mirror of wxhaskell lying around since early July and just never went public with it. So tonight, after TD offered to host the darcs stuff, I finally dusted it off, and converted my Unicode mega-patch into 5 darcs patches and uploaded the whole deal on my homepage. I'm not linking it, because it's really supposed to be temporary. But the rest of the wxhaskell revival team know about it. So it's moving!

wxC and SWIG

SS on the wxc list has suggested we switch from handwriting our wxC stuff to autogenerating it with SWIG. It's been interesting discussing with him. Learned a bit from the process, and got a reminder (duh) that wxC is actually C++ code (of course, what else would it be?), only that it behaves exactly like C code on the outside. Anyway, long term project's looking interesting. SS says that given enough configuration, we should be able to generate the wxC code directly, even including the kind of annotations that wxhaskell needs. But we also agree that this kind of thing is for the long term. Short term priority is to get the new wxhaskell and wxc out the door!


ssh stuff fixed

Fixed the ssh stuff on Saturday, making patches for sftp -q, sftp -b, and --disable-ssh-cm

Apparently, sftp has changed recently, by actually implementing the behaviour they've been documenting for some time, namely:

-b batchfile
Batch mode reads a series of commands from an input batchfile instead of stdin. Since it lacks user interaction it should be used in conjunction with non-interactive authentication.

That'll be man page I'm quoting there. Anyhow, that's part of the reason why issue273 was so weird. There's still other stuff mixed in there. For instance, I don't know why salty-horse's server randomly dies during or before scp when ControlMaster is enabled, nor do I know why scp doesn't give us something nice and useful, like an exit code for bad things afoot. But at least now things work like they should.

Also, my --disable-ssh-cm uses a little bit of evilness, namely, unsafePerformIO . newIORef to simulate global variables like you get in other languages. Eeewww... but it seems like the alternative would be to have a bunch of parameters everywhere, just to keep passing that DisableSSHControlMaster flag all the way down to the ssh calls. Lesser of two evils? I hope I know what I'm doing. #haskell seemed a bit doubtful at first, but basically told me it was ok, if I shouted NOINLINE at the compiler. And I hope this doesn't start a precedent of coding sloppily just because doing it right would be mildly inconvenient. The "global" variable is write once, read many, I figure. It's practically a constant, so it couldn't really hurt, could it?

no query cat

I tried looking at query cat today, but didn't get very far. I think I ought to see what DiffCommand does when you pass it file(s) as an argument.

guilty darcsing

Also, I've been rather active on #darcs and on the bug tracker lately. No, no, I'm not trying to take over the bug tracker (though I suppose other darcsers would be happy to have somebody take charge of it), nor have I been specially assigned to the job. It's just that things are going kinda badly at work. That is to say, I have to write up my yearly progress report, which is kinda hard (though not as bad as writing a paper), and so I just end procrastinating a lot... So as soon as I get my act together workwise and start disciplining myself again, my darcs activity should reduce to pre-July levels. Anyway, that's the general idea. If you see me talking, like a WHOLE lot on mailing lists, it probably just means I'm trying to avoid something important.

patch, match, matches

I sometimes wonder if we should simplify the patch matching interface, or at least document fewer commands. At the very least, it seems we could just nix --patch altogether and replace it by --match='name Foo'.

Also, maybe we should just get rid of the distinction between singular and plural forms. --match should just match everything, and the --last should be used to select among these matches. In fact, I think that's how it already behaves, and that the doc is just a little bit out of date.

Finally, I would even be tempted to get rid of --tag (and likewise --from-tag, --to-tag), and just implement something like --match='tag '.

I suppose we could keep around the old flags for users who are accustomed to them (although I doubt people would really miss them...) and just simplify the documentation.



I just spent today debugging some ssh stuff with a user. Oh man. It seems like everytime I submit a patch, I have to submit ten other patches afterwards to correct bugs in my first patch, and bugs in my bugfixes.


query cat

Did I just promise to implement 'darcs query cat'? Gah, no, bad eric! Extra commitments bad! The most surefire way to break your current promises is take on new ones. It should be easy though. But you know it goes when you say stuff like that...


updated images

On a random burst of inspiration, I have finally gotten around to updating the images used in Understanding Darcs. They include some ideas from #darcs, namely Heffalump's suggestion that I colour the _darcs stuff differently than the working dir. Also, I have uploaded the Omnigraffle sources for these diagrams so that you can look at it and go "Ugh! XML!", or open it on your Mac.

Yeah, yeah, I know I should be using something Free-er like Inkscape... but Omnigraffle, man... it's so fantastically easy to use! Aack, no! There I go, I'm promoting non-free software... Nooooo (well then again, I'm still addicted to the comfort of my Mac, though Ubuntu's looking better and better these days, so I'm pretty much screwed for ideology in either case)

See, this is the kind of stuff I should be working in my free time when I'm looking for something easy. Much more constructive, and even massages the creative juices a tiny bit, much better than, say, going on a 16 hour Freeciv binge... which isn't something I would... actually... do... of course.

Updated again - 23:20

Another update, 8 hours later. This time, went for a model which makes it possible to represent everything in one picture (instead of having a before/after comparison).

That speeds up my diagram-development time considerably. It's already pretty smooth sailing, thanks to layers, but having half as many layers as before is always welcome.

Also added diagrams for revert, unrecord, obliterate.

Anyway, I'd better not get too eager about this book. I do have real work to do, after all. Also, a few diagrams by themselves probably isn't going to make things that much easier for the user. We'll need actual examples, and probably a patient walkthrough, something which I probably do not have the energy to do.


ssh does indeed invoke a shell

And so continues our saga of Eric Doesn't Actually Know How Computers Work...

New discovery of the day? SSH does indeed invoke a shell when you do something like ssh myserver mycommand I always somehow figured that when you did that, magically mycommand would be invoked, like really first thing when you log in, no shell or nuthing. Nope, that's not how it works, and come to think of it, that kinda makes sense, right, because the computer gets to enforce what the user runs when (s)he logs in (duh). If it didn't go through a shell, then what would be the point of having that bit in /etc/passwd that tells the computer what shell to run? The user could totally bypass that by saying ssh myserver /launch/ze/missles. Oh wait... then again, maybe it's not for security reasons, because the user wouldn't have +x on /launch/ze/missles (but I am le tired!)... ugh, it's late, and the later it gets the more easily I confuse myself. Ok, so point being, ssh invokes a shell when you try to launch a command through it. Check.

Makes my issue223 kinda redundant, then, don't it?

the wikibook

Oh, and a minor note, I have slightly fleshed out the Understanding Darcs wikibook. Now, you might think that having a wikibook is redundant with either the Darcs manual, or the Darcs wiki, or both, but I would tend to disagree. I'd like you first of all to think of the wikibook not as a Wiki, but a Book. See, we got three things here, a Manual, a Wiki and a Book.

The way I figure, a Manual's job is to be terse and complete. It needs to be a good reference guide, the kind of thing that mechanics can thumb through without wading through a bunch of useful "helpful" stuff. The K+R book is what comes to mind when I think of this. No nonsense, here's everything you need to know. Of course, a Manual can be friendly if it wants, but only as long as said friendliness does not get in the way of its core mission, thumb-through-ability.

Now what's a software Wiki's job? Not to be friendly either! I'm not sure what I'd put down as its core mission, because you know, if anything wikis are meant to be chaotic and messy. No more than neccesary, of course; it's always nice to have someone come in and try to sweep things around and put things in their place. I guess if anything, a Wiki's core mission is to cover the fokelore. In fact, let's not call it Wiki anymore. Abstract over the fact that it's a wiki. A Folklore Repository is meant to know everything that the community knows. It can be friendly if the community is feeling friendly, but really, its main role is sprawl out into all the little niches of Our knowledge (and that's why wikis are ideal for this, because every one of Us can go plug something in).

And now we get to a Book. What's a Book supposed to do (I should call it something else, like a Guide). So scratch that. What's a Guide supposed to do? Be friendly. And that's we don't have yet in the darcs community. We've got the Manual covered (and we rock because our comments are our manual, go David!). We've got the Folklore down, but not alot of Folk and thus, not a lot of lore. But what we're sorely, sorely missing is an actual Guide. And this is where wikibooks comes in. Hyper-text is nice and all, but one thing which makes a document friendly, I think, is it doesn't force you to choose anything. Not even the order that you read stuff. No a Guide should really be telling you, look, ok, of course you can approach this any way you want, but if you listen to the way I tell it, if you follow me, I will tell you a coherent story. I might be full of crap about this, but in order to make a Guide work, you have to make it sequential. Point being, a Guide needs to be a book, not a wiki. You can put hypertext in it to make it richer, but there must be a canonical order for users to fall back on. Of course, then why use wikibooks? Because I want to author this with the community. I don't think I can pull it off myself. What we're producing is not a real Guide, but sort of a compromise between Folklore and a Guide. But then... why Wikibooks? Why not just put the Guide on the darcs wiki? Oh technical reasons. MoinMoin isn't the easiest thing to work with for fancy stuff. I wish there was a latex-based wiki out there. Like good. Well, actually, there's another part to that, in that I want it on wikibooks, because I want editors to look at that thing and think Book (not Wiki). Book as in, let me try to be pedagogical. Not Wiki as in, let me slap down what I know any old way.

There ya go. Three paragraphs of rambling nonsense with Capital Letters liberally sprinkled throughout. I'd better go home and try to do something useful with my time instead.


windows, ssh stuff, dates and the mystery bug

Stayed home from work yesterday, giving myself the excuse that I was sick. Probably should have gone to work instead, because it turns out I was feeling ok enough to do a bit of darcs-hacking. Also played hooky a bit this morning (it's 11:06), but overall, I'm glad to have spent time getting this stuff out of the way... clears my head, let's me focus on other things.

windows and weird filenames

A user on IRC was trying to work around issue53 where Windows enforces a bunch of naming conventions like "don't start your filenames with AUX". I don't think I personally am going to do something about this, but my proposal is that, when we are running on Windows, we should treat patches that affect such files as affecting some other file instead, one with a translated name. So if we have a patch that affects AUX.dtd, we should apply the changes to -AUX.dtd or something; and print out a warning saying what we have done and why. This solution at least allows the patches to apply, but it does have some problems of its own, like (1) what if a file with the translated name already exists? (2) what if the user tries to modify the translated file? Do we want to recognise that? [I'd say, we probably should, but rather than let the user record changes, we just say "Whoops! you don't want to touch this file. Please mv it to something safe instead."] Mmmhh. I dunno if this is going to work, or if it's just going to make things super-complicated and introduce a bunch of random bloat. Well, in any case, we should at least detect the problem and tell the user about it. I suppose simply ignoring such files (and printing a warning) is just as good, and much simpler to boot. (If we were to ignore them, we should at least try to handle the mv, though, although that too is complicated)

get --to-match

Whilst trying out the IRC-user's problem on the darcs repository, I ran into this.

% darcs get --to-match='exact "More fixes to unrecord."' ~/darcsImpl/stable
Copying patch 3831 of 3831... done!
darcs: failed to read patch in get_extra:
Sun May 22 13:40:59 GMT 2005 David Roundy
* extend revert_interactive test to do a trickier revert.
Perhaps this is a 'partial' repository?

Ouch! I should check the bug tracker and see if we have anything like it.

plink, Windows, ssh stuff

We had decided to reject my new ControlMaster patch because it was fragile, and then we weren't sure about the other patches which were essentially supposed to make Windows shut up when doing ssh stuff (so we don't get spurious plink -O error messages). I finally had a chance to sit down and review these patches. It seems that it is ok for us to apply them independently of the control master stuff. I have resubmitted the patches and made a request for review. Well, all patch submissions are implicitly a request for review, but I wanted to particularly call attention to this bit.

dates and the mystery bug

I had a filed a bug report for a mysterious issue involving the darcs repository inventory. Juliusz looked into it and found that it was due to a cleanDate patch. The basic problem is that PatchInfo.make_filename uses cleanDate to parse the date info in old-school patches. Old school patches write their dates in human-readable format, which is rather useless because it's just an internal representation and harder to parse.

Case in point, the mystery bug. I had submitted a patch to fix issue173 (timezones not recognised correctly)... what the patch does is to correct cleanDate so that dates are converted to UTC before being printed out. I think this is the correct behaviour, because otherwise, timezones are just truncated; which would be very bad because somebody reading the time string in would have little choice but to assume UTC.

So I think my patch is correct: but it breaks old patches, because the patch in question was dated Sun Sep 21 11:57:26 EDT 2003, which is intepreted

before: 2003-09-21 11:57 (wrong!)
after: 2003-09-21 15:57 (EDT is UTC-4, so add 4 back)

Unfortunately, the filename generated was using the incorrect time (2003-09-21 11:57). Ick. So what I proposed is that we continue supporting this broken behaviour (it doesn't really matter anyway, it's just what filename we give to it), by using showIsoDateTime.readDate and a small comment saying that this is wrong, but we don't really care.

Anyway, I hope I haven't simply confused myself. I think this analysis of things is correct, maybe the next action is wrong, but I'm pretty sure that's where things went wrong. Sometimes seems that it's impossible to program a computer without being super anal about everything.

patch bundles

I have one particularly bad habit when submitting patches, and that is grouping my patches into thematic bundles, rather than dependency bundles. Why is this bad? It causes confusion! It makes people think that certain patches go together, when in fact the only thing about them is that they are related to common themes, like "date parsing". I need to get a better eye for grouping my patches so that things work out smoother for everybody.


tailor needs a recent CVS

Having trouble bootstrapping from CVS (say, via anonymous pserver on sourceforge)? Try upgrading. It wasn't working for me with cvs 1.10, but 1.11 did the trick.


haskell wikibook moves forward

Ran into dmhouse on #haskell today. One bit of conversation led into another, and before I knew it I was rewriting the entirety of the basic concepts (now called Variables and functions) chapter. I hope it doesn't suck too badly, but I guess I'm not too worried, since the community can always come in and clean up after me later. Also completed the Write Yourself a Scheme in 48 Hours import. It was easy, thanks to the Perl module HTML::WikiConverter.


ssh issue hacking

Revisited one of old demons last nights : poor sleeping habits. Up to end of June, I had managed to make a completely artificial transformation of myself into a morning person, sort of as a neccessity in becoming more effective at work. But last night, I started hacking on SSH issues and ended up doing what the French call a white night... pulling an all-nighter, that is. You know how it goes. You start working on one issue, and actually that itself doesn't take that much time (in this case, a fix for CM-related stuff), but then in the process of testing your stuff you notice other problems (like, me trying to run test this on Putty with my Mac) and so you start hacking on that, and your stupid tenacity makes it so that you don't give up until the very end. Of course, by the end of the night, I was being really really slow, even watching the Corporation on the my computer while waiting for darcs to recompile for the umpthinged time (which of course slowed down the compilation and also made the viewing very choppy and unpleasant).

In my more disciplined days, I would have been smart enough to have told myself that anything I can do at night, I could also do after waking up, and much more efficiently at that (you know, without the fatigue-induced stupidity). Instead of staying up to do darcs hacking, going to bed at 09:00 and then going to work at 15:00, I could have just gone to bed, gotten up early, done my darcs hacking, and still gone to work late, only probably not nearly as late as before. Silly me. I will get back in gear. This was the thing I was afraid of. You take one little holiday and all your (completely artificial) sleep schedule goes all out of whack. Need to get my discipline back and remember that until the end of next year, everything I do needs to be secondary to the thesis.

Anyway, hope my sleep-derived patches actually work as expected, and aren't chuck full of stupidity. Learned a bit about Unix in the process, like what /dev/tty does.


laziness, unsafePerformIO, atexit

Just learned a bunch of neat stuff this weekend. Had a discussion on darcs-devel with Juliusz over issue171. I had propoposed sort of a naive fix based on looking for ssh paths on the command line arguments, and he suggested instead something that would call the ssh control master when need be, using laziness and unsafePerformIO. My reaction to this was... "uh, sounds nice, but I don't know how?". So after I submit my patch, he shows me what he has in mind, and lightbulb! It makes perfect sense when you look at it, but it so is not something I could have come up with by myself. The pattern goes like this:

type Bar = ...

foo :: Bar
foo = unsafePerformIO fooIO

fooIO :: IO Bar

And the effect is that when you call foo, the embedded IO action gets executed when needed (because of laziness), but only once! Haskell is still a pretty mysterious and magical language to me, but the way I like to think of it goes like this: we're doing functional programming, right, so once we know the value for something, that value is never going change, so there's no point reevaluating it. We just keep it around all pointer-like (hand waves). Kinda scary how long I've been getting by without really understanding how things work underneath.

There's two things I do with laziness at work:
  1. learn to live with it - i.e. program without actually caring about when things actually happen
  2. use it to simplify code (since it's lazy and you don't care, you can write some things in a naive-looking way and know that they'll work just fine)
but my Haskell still has not reached the point where you actually reach out and exploit the laziness, really bend it to your will as opposed to just accepting it as a free, if occasionally annoying, gift. I don't mean to be making a really big deal out of this, seems to be something we do a lot in the darcs code (lazy, unsafe, magical, yaaaawn), but from my fresh newbie eyes, little things like that just make you go woah.


The other wow-neat moment was looking at the AtExit code. Not something I neccesarily understand, although I do recognise bits and pieces of Concurrent Haskell that I gleaned from one the Simons' Asynchronous Exceptions paper (we needed asynchronous exceptions at work), but very neat nonetheles. The net effect is that the unsafe+lazy idiom that Juliusz showed me combined with Tomasz's atexit means that all the SSH stuff is now all nice and encapsulated. No details! The ssh control master stuff just works magically and the person invoking it doesn't have to know a danged thing about it. This black box has been brought to you by lazy evaluation and people with names that end in Z.

patch set

Not only did I not go to work this weekend like I told myself I would be doing, I even procrastinated on my hobby. Basically put off till almost bedtime looking into darcs internals and figuring out what the heck a patch set is so that I can implement the minimal context function. My one insight after unrolling the big ball-o-yarn is that there probably is some relationship between patch sets and inventories; and that the best way to find out what a patch set was would be to look at the code that actually makes them out of thin air. So now the function I'm staring at is DarcsRepo.read_repo_private. Slowly getting closer. Guess I'll figure more stuff out next weekend.


still around

I have still been working on darcs since my last post, just at a much reduced rate at less than half an hour a day assuming it's not one of the (many) days that I'm not just way too tired to think about darcs. Managed to clear off a couple of hours here and there today. Mostly spent it writing regression tests for stuff I had broken in my previous patch (for implementing help --match), and well as slightly more aggressively testing the rmdir changes I made. Writing regression tests is like washing the dishes, I guess, extraordinarily dull but also very satisfying when you get it done.

Next I shall concentrate whatever bits and pieces of my darcs energy on minimal context.

If I get that done (and this might take forever with my new darcs pace), I'll continue working on the wikibook.


monad tutorial, slow darcs

monads tutorial

Fixed one of the flaws in my monads as spacesuits tutorial (well, nuclear waste containers rather) on wikibooks. It was in my definition of the get and put functions where I was accepting an argument too many (and then discarding it). The tricky bit was that using the correct definition of get/put involved introducing the anonymous bind >> operator to the reader. I hope I did it right... I think it's probably clearer anyway that I went ahead and did this... it makes the bit where I explain IO a tiny bit less shaky.

Though this is a wiki, I seem to be in the habit of (1) profusely thanking people who modify the tutorial (2) reverting their change with a plea to read my comments on the discussion page. It's happened three times, already, one with ihope127's replacement of € with |> (which was a reasonable thing for him to do, since € wasn't Haskell, but € is useful because you can think of it as $, but backwards), another time with the get/put thing and a third with the use of the modify function. I really really DO want to collaborate, though (hence the profuse thanks), it's just that I keep disagreeing with what people do to it. I'm not a control freak, really. I hope I'm not, anyway. I mean, I do try to solicit the other party's opinion on matters and try to integrate what s/he thinks into the writing. Hope I'm not turning anybody off from the project.

slow darcs hacking

My darcs development is going soooo slowly. Part of it is because I'm working on it like 15 minutes a day, instead of a few hours, and 15 minutes isn't enough to get you into that state of intense concentration where everything just flows out of your fingers. I'll need to allocate a somewhat larger chunk of weekend to darcs, just so I can keep any promises I made. The other part is that it's kinda boring writing test suites, and I've got a little bit of that to be doing. Need to get a test suite for matching, and one for mv/rmdir testing out the issue154 fix. But I am workin' on it, making little bits of progress here and there.

That's the way it'll have to be I guess... it has occured to me that the only way I'm going to finish my thesis in the allotted 3 years is by working really fricking hard (I've got slightly under 1.5 years to go), so bye-bye hobbies. Oh well, it's been fun and very educational, not that this is goodbye darcsers or anything.


cutting back

I've just sent my issue91 and resubmitted the issue154 patch... wow this goes a lot slower when you're only working in 45 minute increments. I'm going to be radically scaling back on my darcs activity until at least 19 April. Got some paper submission deadlines till then, and I'm basically going into thesis-overdrive. I'm only a 2nd year student, no writing up to do, but I'm going to need to bust ass if I want to emerge from this whole process with my fancy degree and to actually deserve it.

Still have some remaining darcs commitments: the wikibook still has huge gaping holes and I promised David+Juliusz that I'd implement the minimal_context stuff. Not that it would be hard for them to do it, the whole point was that it was easy and (1) they could farm it out (2) this would be a good way for a yellow belt like me to get to know some of the real meat behind darcs. So I still aim to get those done, but other than that, I'm hoping to get focused from here on out.



Got patches in to fix issue154. Zachary Landau pointed out that I had some arguments in a non-conventional order, so I unrecorded and flipped the arguments around. Good thing too. In the process, I spotted a bunch of cases where I was setting the flag to indicate that I was in the working directory, when that clearly was not the case. Being forced to go through this a second time was quite useful for spotting the errors.

Spent today working on help. Wasted a bunch of time trying to refactor some of the command line parsing stuff to use my disambiguate_commands function, but I just kept breaking darcs. Ended up deciding it wasn't worth it. Not really saving that much code, anyway.

Implemented issue91. Easy enough... maybe should have left it to newer developers, reel them in with breadcrumbs exactly the way I got sucked in. I did try to refactor PatchMatch.lhs in the process. It's one of those bad refactors, the kind that makes nice airy looking code and makes it compact and unfriendly. Good refactors, on the other hand, take a bunch of useless verbiage and make it concise. Short and sweet. Hmm... can't really convey this in a non-arbiratry-sounding way.

Whoah! It's past my new good eric bedtime. Need to learn to renounce, leave things for another day. Good night.



It's that time of year again, the one where all submission deadlines converge. I've been putting in many hours at work lately trying to get something semi-publishable on time. Strangely, I've gotten into this nice habit of going to bed before 2h and getting to work around 10h. I'm loving it! More please! I've got this fantasy of me getting up at 7h, having a good breakfast, reading some articles for work, and then making my way calm and happy because I had made the effort to nourish my scientific brain. I dunno how long this will last, or why I seem to think that getting up earlier is better.

Anyway, been working on the PatchApply stuff for bug 154. Got the flag in, now I just have to see to all the stuff that calls an apply function. Not very clear what's going on with apply_to_slurpy though...


Repository diagrams

I just uploaded 9 darcs repository diagrams for the darcs model chapter of the wikibook. I'm not sure these are really useful, that they actually help communicate the idea behind darcs, but it was worth a shot. Just taking a break from all this patch theory stuff, doing something easy for a change. Got a friend at work that seems to get confused by all the darcs commands, so maybe a little visual support could be useful. Or it could just add to the confusion.


patch theory intro

Spent this afternoon finishing off the rewrite of the patch theory chapter. Like it a lot better. There's still a bit to polish off regarding the definition of a merge, and the commutation with inverse property, but it's definitely progress. Don't know if I have the energy to work on the other two chapters. Probably charge the mental batteries for a while, go work on something else. We'll have to see.


Constructive patch theory

I have not only been procrastinating on the Understanding darcs rewrite but have been a total flake this week on darcs and life in general.

Think I was having a somewhat bad couple of weeks and have been self-medicating by picking up a short freeciv addiction. I hate freeciv. I don't know what I can't shake it. It is something I do not find enjoyable, but every once in a while, I get this inexplicable craving, and well, you know how it goes. Lost sleep. Bad dietary habits. And all for a stupid game you've played over and over again (each time badly) with no surprises and no change in strategy. Anyway, I'm glad that's done with. Geez, even watching Firefly was better than playing freeciv.

Right... darcs. I've finally started the rewrite that I had been promising Arjan. Rewriting is really good for you. Forces you to look at crufty old bits of text and say to yourself, "waitasecond, that doesn't make one bit of sense!''. There's still a couple of holes in the introductory stuff. Need to write the complex undo bit, and reexplain what a context is, because I think the way I have it now is probably flat out wrong.

Holy shit. Did it just become 3h? But... is today leap forward day? It is indeed! Gah! And all this time I was being impressed by myself for being tired before 2h and wanting to call it an early night. Foiled!

Oh, and uh, Juliusz accepted the ssh patches today, along with the diff command stuff. Glad that's off my plate and I can move on to other stuff, like the wikibook.


At last, ssh multiplexing.

Patches sent to the list.

Well, glad I got that done. Hope it actually works as advertised. Unfortunately, this is not using Ganesh's idea, but I guess I'll let somebody more competent take care of that. This easier solution only works for people who have a fancy new ControlMaster-enabled ssh. It is nice not to have to type my password a whole bunch of times.


Whilst waiting for my tests to complete (I use record --no-test, followed by darcs trackdown when I'm almost ready to send), I took the opportunity to freshen my --diff-command patch and the refactoring stuff. Yeah, I know Daan's already sent his --external-diff one, but mine handles something which is perculiar to Macs, that being opendiff. The thing about opendiff aka FileMerge is that it quits immediately, leaving a subprocess on chew on the diff. But if darcs automatically cleans things up after opendiff exits, then FileMerge gets confused. The solution, at least, the one I borrowed from --external-merge, is to make the user press a key to continue. This way, we don't do the temp file cleanup until we really have to. The other thing is that my version of the patch is pickier about keeping things refactored. Oh well. I guess I don't really care either way, since I don't use --external-merge or --external-diff. I just wanted to get rid of my patches. Had been sitting around since January. What had happened was that Daan asked if the feature was there, I volunteered to implement it, sent it off, Juliusz got busy, and I forgot to tell Daan that there was a patch he could play with. So he decided to go implement it himself, and now we have two patches that do the same thing :-)


ssh control master

Made one useful bit of progress in the ssh control master stuff.

Before, I was having trouble with getting the control master running and out of the way. I didn't really know how to launch stuff in the background, so I basically forked the thing and polled the control master every 3 seconds to see if it was connected or not. But that was a really fragile setup, and sometimes, if I didn't type my password fast enough, I wouldn't be able to get a connection.

Tonight I have found a much simpler way to get the CM running: I just use the -f flag to make it go to background right before running the command, that is, only after it has completed the connection. This way, I don't need wait around polling, to see if the CM is running. This is terribly embarrasing how much mysterious all this process stuff is to -- seems shameful to call myself a computer scientist and not at least have some basic notions of how operating systems work. I built a toy OS for school once, but that was a really long time ago. Anyway, it does seem to work. All I know is that the exec function is a piece of darcs-internal code that makes some FFI call to a thing called smart_wait. And I guess smart_wait is happy to return if the thing goes to background or something like that.

Anyway, I was scratching my head for a while as to why I could get darcs put to work, but not darcs get. Turns out that the -S flag to scp means something else than it does for ssh. But no fear, we can use -o ControlMaster instead. Ooh tired. Will have to save this for tomorrow. Something to look forward to. Killing this project at last.

cvs keywords

A self-described newbie posted a message on darcs-users asking if there was any CVS keyword type functionality. Not something I care very much about, but I did find it kind of useful back in the dark days of CVS. Maybe it could also be useful to have in darcs. Of course, there are reasons why this kind of thing doesn't make any sense for us -- we don't do versions -- but maybe something approximative might be good enough for everyday needs.


back to darcs life

Have finished watching Firefly. Enjoyed it very much, but I am quite happy to be free of the shackles of mindless albeit high quality entertainment. So, what's on the plate?

Understanding darcs

Arjan had some bug fixes for the diagrams I made, basically a label being on the wrong transition, which makes things just wrong (I was rather uneasy about that, glad he picked up on that too). He'd also prefer a more constructive approach to explaining things. At first, I was rather hesitant, because I thought this would be mean backing away from the focus-on-a-concrete-story and explain-things-as-you-need-them approach, but then he showed me that the story could easily be extended with some concrete, uncontrived examples for the simple stuff. That is, you can at times want to commute patches outside of a merge situation. So I was happier with that.


Met a happy customer of the TracOnDarcs howto on #darcs. That was gratifying. Not the thanks, of course, besides, Lele deserves the lion's share of that, but it's always a big boost to your ego to see that something you made was genuinely useful to somebody, even if that consists only of an instruction manual. That's the biggest compliment you can pay anybody in the free-content/free-software universe: use their stuff.


no darcs for a while

Have not been working on any darcs stuff lately, and probably not till the end of this week. I, uh... started watching Serenity and season 1 of Firefly.


early to bed

Alright. I left work early today because I was feeling really tired... gee wonder why.

Have a friend who is currently learning Haskell. He asked me a question which ultimately had to do with Haskell and its use of layout, so after answering his question, I went ahead of wrote up what I knew in a new wikibooks module on Haskell indentation. What's funny is that I've been haskelling for two years now, and I still don't really know what the layout rules are. So I don't have all the elements I need to complete this page, but it's good way to learn. Would be useful to know for sure what I can and cannot do, instead of just using intuition.

Other than that, I also wrote up the results of today's discussion with Arjan. Think tomorrow I'll work on coding stuff instead. Need to let the conflictors stuff digest for a while.


posting from work

Crap! What happened to my discpline of keeping work and play neatly separated? Not that I completely believe it in, though. I have learned a great of Haskell by working on darcs, much more than if I had just continued plodding on with GenI (work).

Anyway, I just felt the need to rejoice. After last night's (this morning's) wikibooks debacle, I now understand ordinary conflictors! Not the complicated ones, mind you, no middle anything, just the simple stuff.

14:24 [kowey] could i check something with you on conflictors?
14:24 [arjanb] sure
14:24 [kowey] i've worked this out backwards, and want to make sure i'm not wrong, here
14:25 [kowey] say A and B conflict (this is the beer and pasta example in the wikibook)
14:25 [kowey] we want to pull A into B's side...
14:25 [kowey] so we want to calculate some A1 that we can apply like BA1
14:25 [kowey] so far so good?
14:25 [arjanb] yes
14:26 [kowey] in order to do this, we have to calculate A^-1
14:26 [kowey] and commute that with B to get (B1 A1^-1)
14:26 [kowey] so, in the beer and pasta example
14:26 [kowey] A is "add beer to the shopping list"
14:27 [kowey] A^-1 is "remove beer from the shopping list"
14:27 [kowey] since A^-1 and B conflict; we have to use forced commutation
14:28 [kowey] and when you do a forced commutation, the effect of A1^-1 is exactly the same as the effect of B
14:28 [kowey] so A1^-1 says "add pasta to the shopping list"
14:28 [kowey] and when you take the inverse of that, you get "remove pasta from the shopping list"
14:28 [kowey] which you can then apply to B to cancel the pasta out
14:29 [kowey] is that right?
14:29 [arjanb] yes though i prefer to do it the other way around
14:29 [kowey] you mean, pull B into A or something else?
14:31 [arjanb] make first a sequence B B^-1 A then commute to B A1 (B1^-1)
14:31 [kowey] that sounds clearer

Arjan made a very good point that permutivity is a property of all patches, not just conflictors. After some discussion, we came to the conclusion that it would be useful to have an intermediary chapter for formalising patch theory. We're going to put stuff in it like: symmetry of merging, what happens when you have N non-conflicting patches, and the stuff that Ganesh is working on.

Argh! How did I get here again? 4h30... exhausted, muddled thinking at home, muddle thinking at work. Must put a stop to this nonsense. Spent some time working on the ssh stuff, now that Juliusz has applied my latest salvo of patches. It compiles, but doesn't do what I want. While waiting for it to compile, I decided to continue working on the Understanding darcs wikibook... was making great progress, things were starting to make perfect sense. But then, I think it was somewhere around 3h30, I realised I had gotten everything wrong. MRRRRHH. After I had even bugged someone on IRC to go guinea pig the new text.


this is getting ridiculous

4h30 on a frickin workday! And twice in a row too, but it's so hard to stop when things finally start working. After all my refactoring of SelectChanges, I think I've fixed the graphical patch selection for obliterate. The basic idea is that the gui and text selection modules should share as much code as conveniently possible. Anyway, now that this scraiest looking bug is fixed, I have resubmitted my wxDarcs stuff. It's still broken in a couple of known ways and probably a million other unknown ones, but it's important for me to get it out the door so that people can start hacking on it, and so that I can move on to other stuff like ssh and Understanding darcs. We all know it's broken. Nobody's going to claim that the GUI is working, but the code should at least be there for people to play with.


refactored SelectChanges.lhs

I'm probably being a little quick to judge here, but the function with_any_selected_change in SelectChanges.lhs is some serious spaghetti. I'll bet it started out all nice and simple, and we just kept adding functionality to it one tiny feature at time, and us the darcs developers being so used to the code, never noticing that things were getting out of hand.

It took my all Sunday staring at it, making notes on the wiki, and finally tearing it to pieces and putting it back together (just rearranging code) to get a clearer picture what it was doing. I hope my refactor is correct, that it doesn't introduce any weird bugs into the code. One thing I'm slighly worried about is that I took out seemingly pointless seq, something that looks like other_ps `seq` ps' where, if I understand correctly, other_ps is defined to be []. Anyway, so I seperated the notion of counting patches from that of simply deciding which patches to consider. This way I can reuse the latter function in the gui selector. The code compiles. I only hope it does what it's supposed to.


absolute file stuff / mutt / SelectChanges

Sent off my absolute file patches this morning. I hope they do the right thing. I don't know, but I don't think it want to play with this anymore. Hopefully a third person can look at this because Juliusz is nervous about it and so am I... would be useful if somebody else came in and said, "yes, this is the way to go" or "no! are you crazy?"

Spent most of my hack day (i.e. the part where I wasn't at the gym or grocery shopping) switching to mutt on my laptop. I've been using mutt for a long time, but only at one account at a time, most recently at work. Spent some time splitting my configuration up and automating the relationship between my aliases and save hooks: makefiles and sed are useful for that. Whowouldathunkit. Using make to automatically generate parts of your muttrc. Wish I had thought of it earlier. Anyway, pleased with the switch. Apple Mail infuriates me in many small ways. I also switched to zsh today. Don't know why. Random impulse.

Other than that, I'm slowly starting to understand how SelectChanges works. It's kind of interesting, the frontier between the outer and middle layers of darcs (*). Also very gratifying. I like understanding stuff. You just have to stare at it long enough, and poke at it at the right angles, and eventually it opens up. The trick for SelectChanges was to grep with_selected in the code and write it up as a table on the wiki. I still don't actually know how it all works, but I've got a clearer picture what questions I need to be asking next.

I tend to see darcs in three layers... this is my naive view so far: you got an outer layer which consists of the commands and all their helper code, including stuff to invoke sendmail, etc; next you have the middle layer which deals with the various patch types and how they commute; and finally you have the inner layer, which is the core patch theory stuff. It's probably very hard to distinguish beteen the middle and inner layers for example.


absolute directories

Two things: got the absolute directories tests running, although I had to hack them up a bit to fix what seems to be darcs bitrot and weird perl. Hope my modifications aren't actually breaking the tests.

Also, I've been going over my patch a little more thoroughly, and have found a few bugs. End result is that patch deux is smaller and cleaner. I'm still not entirely sure if it's correct though, and am hoping for some review from fellow developers. Here's the issues with my patch that I've fixed:
  1. Changes.lhs - was not accounting for the fact that repodir could be relative path; fixed by generalising fix_filepaths_here to fix_filepaths_wrt somerepo, where fix_filepaths_wrt has some extra smarts for detecting what kind of path the current repository is
  2. DarcsCommands.lhs - forgot that ghc 6.2.2 does not have canonicalizePath; tough luck, got rid of code which canonicalizes all the absolute paths. Disadvantage is that now, absolute paths detection doesn't always work. Advantage is that the code is a bit tidier and the patch is smaller
  3. Apply.lhs - was needlessly performing the absolute path conversion
  4. FilePathUtils.lhs - was not producing the right error message, and was not strict enough on what kind of repository paths it expects

Sigh... these aren't fixes to darcs, mind you. They're fixes to my patch, which were supposed to fix darcs.

Ok, wow, it's almost 4 in the morning. I keeping telling myself I'll go to bed earlier, yet I keep getting sucked in to stuff like this...


wxDarcs, absolute paths and conflictors

Wow, I've been really tired lately. Ought to be going to bed earlier or something.


Right, so one little bit of good news to lift my spirits: I managed to fix a couple of layout bugs today. For the OS X Tiger layout issue, all I had to do was pack my splitter window inside its own panel, and everything was ok. As a more general issue, I finally figured out how to force one of my buttons to the very bottom of screen (nitpicky that way) -- I just pack all the other buttons, the ones that go on top into their own column. Gui programming can be a pain that.

I also know why the obliterate gui was behaving funny - it seems to be more or less obliterate the reverse of the patches you tell it to. So if you've go 3 patches, foo bar and baz, and you tell it to obliterate foo, it will end up obliterating baz. It seems like gui_select was never implemeneted to deal with is_reverse, which is probably why David (i assume) didn't allow Unrecord/Unpull/Obliterate to accept --gui in the first place. So my new job if I want to get obliterating right is to figure out how to deal with selecting patches in reverse. It's kinda funny -- all this first middle last stuff is vaguely reminiscent of how Vijay-Shanker and Weir 1993 represent chart items in their parsing algorithm (more related to eric job stuff). Of course, there is probably zero relationship between the two except for this notion of head, middle tail... but who knows?

absolute paths

Anyway, after looking at that stuff, I got discouraged and decided to tackle some of my absolute path actions instead. Applied my patch -- very few conflicts -- and cleaned up some of my own code. Now I need to test it out, and sit down and figure out where it could go wrong. I hope the code is right though, because I would really like to get rid of it as soon as possible, and move on to other stuff like Understanding darcs.


Starting to read the mailing list in chronological order. I had forgotten that I did not in fact download the entire archives. Wonder if there's any way I can convert this thing into something a lot friendlier for mass-reading. Hopefully the combination of this and my FOSDEM notes will allow me to produce a useful introduction.


Juliusz seems at last to have had a pocket of free time to apply a few patches. Unfortunately, this breaks the wxDarcs (easy to fix). I'm kinda hesitant about sending these patches in. The darcs gui is really horribly horribly broken, the way I have it set up. Consider, for instance, that it obliterates the wrong patches! Sigh.

There's also my patch for fixing the absolute directory stuff which I need to think about and confirm.

Man... Been a long day. Time for bed.


darcs developers at fosdem 2006!

Unfortunately, I didn't think to do this on Saturday when there were more of us, so sadly, Juliusz and Andres are missing from this little video:

In the video, you get David, Arjan, Ganesh and me (Eric). You also get members of the future darcs users group, Dmitry, Alexander, Michael, and Joseph. Although, I might add Dmitry has expressed a certain interest in formalising patch theory as a sequent calculus, or something like that, so maybe the darcs developers will have another logician on their side?

Oh, yes and I did mention a videoblog somewhere. This is being cross-posted to a collective video blog shared by a small group of friends from high school, gfdjax.

understanding darcs

I was supposed to spend my day off doing laundry, getting my hair cut, and running a million little errands, but instead I spent it writing my patch theory introduction in Understanding darcs. Oh well, at least I now know how merging works in the very simplest non-conflicting cases. Typical pattern for me. If I want to understand how something works, the best way for me to go about it is to write something in wikibooks about it.


In preparation for my FOSDEM learn-about-conflictors mission, I am trying to catch up on patch theory stuff by reading this paper:

darcs get http://darcs.net/darcs-patch-theory
cd theory
make paper.ps

Now this is a fine example of literate haskell, where the literacy actually helps you understand what's going on, much more than it gets in the way of the code. Maybe it's also because some things are more suited to the literate way of programming than others, and this is one of them.

Oh yeah, dabbled with the ssh stuff. Think I had made more progress than I orginally thought; just hadn't noticed because I had not written the code to actually use the control master instead of just launching it, so of course, I was typing my password a gazillion times and not understanding why I couldn't connect. Silly me. Not done yet, but I'm a bit more optimistic now.


arrows as conveyor belts

I think I've finally found the visual key to understanding arrows. Where regular functions are boxes that accept input and produce output, arrows are the same thing with conveyor belts. I think this helps to visualise what the various operators are for. See this diagram, for example.

I've got diagrams for arr, first, second and ***. Still don't know really what I'm talking about though, so I'm a bit hestitant to put all this on wikibooks just yet.

Omnigraffle is a great tool. I'd love to see the free and open source software community do as well as Omnigroup.

Oh and darcs news: arjanb has charged me with a mission for FOSDEM: go to talk to the conflictors people until I understand it somewhat, and then write it down somewhere so that other people can understand it. I hope I'm up to this one! I think I'd like to make this part of a general project: writing a friendly Understanding Darcs booklet - combination of latex and hevea. I've already dreaming up diagrams to show the lifecycle of potential patches (changes) -> named patches -> exported patches, as well as the difference between the working directory and the pristine tree. What I figure is that patch theory and conflictors could be the "advanced" section of this booklet.

Argh. Too many hobbies. Saturation. What a great thing to be complaining about, though... I guess I should be thankful.


no darcs lately

Haven't had much of a chance to work on darcs lately. Some bits and pieces of work on the ssh control master stuff. I think I'm stuck somewhere on the code which launches the control master in the background and asks it every 3 seconds if it's ready yet. Or not, maybe that's fixed already. Geez, I can never remember what I'm doing anymore. Senility strikes in my mid 20s.

Been interested lately in learning what the heck arrows are, and working on the Haskell wikibook, so put the darcs down for a bit.

Flakey like that.



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
\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
-- 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?


unexpected burst of darcs hacking

Worked on two things tonight:

Tommy doesn't mind the silly code in the date parser, finds it rather cute and thinks we should really just be trapping the error and printing out an amusing error message. I'll go with it, but before doing that, I wanted to look deeper into what was making this break. Roughly, it's some kind of MAXINT overflow, but the question I had for myself was why it was overflowing in two different places on his machine vs. mine. Turns out that the library System.Time is buggy! Try this at home, normalizeTimeDiff $ noTimeDiff { tdYear = 1 } and you'll get some weird stuff. Igloo will submit a bug report and a patch to the Haskell folks. Yay!

Riadstradh asked me if I had gotten around to making a dmg for Tiger (like i said i would). Tickled to see either (a) people being nice and testing things out or (b) showing an interest in wxDarcs. The first binary I made didn't work. Turns out you also have to make sure to idtool change the libs required by the libs that you copy. So now my script for copying frameworks around loops around and tries to get all bases covered. Hope it works this time.


multiplexing over a single ssh connection

One of my friends at work today was complaining about darcs and the gazillion ssh connections it sometimes has to make, so I decided to take on zooko's feature request that we multiplex over a single ssh connection. It's not turning out to be very easy. One problem is that I need to work out how the business with launching the ssh control master is going to work. The thing has to be running in the background while darcs goes about it business. What I would like to be able to do is launch the thing, but wait until the connection has actually been established before returning. This way, the next time darcs wants to call ssh, it doesn't have to worry about the control master. Will have to think about this some more. In the worst case, we could just give friendly instructions on how to do this: I've already updated the FAQ on the wiki, suggesting that the user set DARCS_SSH='ssh -S the_control_file'.


no darcs lately

Have been taking a break from darcs hacking for a while.

Lately working on the Haskell wikibook, mostly importing my monads and space suits tutorial into the monads chapter as well as learning and writing about monad transformers. You'll note that the monad transforms text is a remix of Jeff Newburn's All about Monads tutorial with even more spoon feeding, because slow people like me need that kind of thing. Kudos to Jeff for granting us wikibookians permission to remix his text and to Paul J. for thinking to ask him about it.

This is greatly blurring the line between work and leisure. I'm learning about monad transformers because I need to use them for something at work, but I'm using a leisure-activity (building a wikibook) as a tool to help me learn.


So tired... skipped work today because i was so so close. But here I am. Checkpoint reached. Got a working prototype of wxdarcs submitted to the list.

Had a long post detailing all the issues I went through, but somehow got lost. That's the trouble with these web tools. You lose stuff so easily.

Tests seem to run slow in gui mode. Can't figure out why.

Bed... at last, I may go to bed.

And go to work tomorrow. Looking forward to doing anything other than my hobby...


another dateparser error

Tommy Pettersson observed today that the dateparser.sh test was failing on "4 score, 7 years ago". Nothing wrong with the date parser itself. Apparantly, his computer doesn't like dates from 87 years back. Mine doesn't like them from 105 years back. But parsing score of years, as well as expressions like "tea time", "bed time" and "proper bed time" is completely silly and pointless, so I submitted some patches to remove this functionality. Functionality I put in on a whim. Geez. I think half of my patches to darcs are corrections to the other half of my patches.

no start twice

Yippee! I found it! And this tiny moment of joy has made the whole miserable sniffly headachy weekend (got a cold) worth it.

I ferreted out the problem by making a small wxhaskell demonstrator and trying to figure out what Control.Exception.bracket is all about. As far as I can tell, it doesn't look like more than just a >>= c >>= b, so we can forget about it. The problem is more to do with the start function. Here's what my tester boiled down to:
main = createGui ""

createGui txt =
do putStrLnAndFlush $ "opening " ++ txt
start $ gui txt
putStrLnAndFlush $ "closing " ++ txt

gui txt =
do f <- frame [text := "Howdy " ++ txt ]
closeBt <- button f [ text := "Close"
, on command := close f ]
spawnBt <- button f [ text := "Spawn"
, on command := createGui $ txt ++ "."
set f [ layout := margin 5 $ column 2 [ widget closeBt
, widget spawnBt ] ]
putStrLnAndFlush $ "gui created " ++ txt

putStrLnAndFlush x = putStrLn x >> hFlush stdout

This demonstrator allows us to replicate the issue I was having with wxDarcs. That is, you click on the spawn button to create a second window, and if you close the second window, it does not seem to come back. Exactly like yesterday, if you close the first window, you get a bus error. All you need to do to fix this is to realise that start indeed performs some kind of voodoo, and this voodoo is something you may only perform once. It was one of my theories, but I had written some code into Record.lhs to not call start, but it didn't seem to work. Maybe I had just confused myself or something. So, the simple fix is just to change the code so it looks more like this:
main = start $ createGui ""

createGui txt =
do putStrLnAndFlush $ "opening " ++ txt
gui txt
putStrLnAndFlush $ "closing " ++ txt

This way, when you call that createGui function from within the gui, you're not calling that start function a second time. Woohoo! Then maybe we're not so far from getting wxDarcs out the door so that other people can hack on it and so that I can start working on other stuff.

Blog Archive