Feeds:
Posts
Comments

I just reinstalled ubuntu on my development laptop because the hard drive seems to have been hosed after a hard reboot. (Wubi is vulnerable to those.)

Everything was backed up on patch-tag, so no major drama.

One annoyance was the cabal install I ran for installing patch-tag was getting hung up on some dependency related to this issue

http://groups.google.com/group/fa.haskell/browse_thread/thread/3e556db4901e1db8?pli=1

only the advice in that thread didn’t help me, since the error I was getting was that

cabal: dependencies conflict: ghc-6.10.1 requires base ==4

uninstalling base seemed like a bad idea, and I knew that this installer had succeed elsewhere.

So, I sshed in to another box where the install had worked, and ran the following script to determine the *exact* package versions that patch-tag was using by doing

ghc-pkg field patch-tag depends

I specified the exact versions (== for every package dependency) in the cabal file in my new virgin environment, and the problem went away.

Shrug.

Hopefully this kind of annoyance will just go away as cabal keeps gettin the kinks worked out and the haskell platform begins a reality.

I just made my first patch to the darcs source, a minor fix correcting an incorrect help message that has always bugged me.

http://lists.osuosl.org/pipermail/darcs-users/2009-April/018914.html

Stuff I have learned:

There are two different build systems with darcs: cabal and make.

Cabal install does the usual thing

Make is what you want if you want to load darcs into ghci. You need to run autoconf first, which means you need autoconf installed — apt-get install autoconf on debuntu. Then just autoconf; configure; make ghci.

Beter to hack on darcs during daytime pacific time, when there are people on the #darcs channel to answer questions. It’s a lot of code to grok!

I was browsing the FileStore code and got to thinking that the FileStore data type rubbed me the wrong way because it hides IO, diluting the Purity of Essence of haskell’s precious type system.

In ghci of our code that uses FileStore:


:t darcsFileStore "/home/thartman/patchwiki/wikis/happstacktest/"
darcsFileStore "/home/thartman/patchwiki/wikis/happstacktest/" :: FileStore

I see that and I think, cool, a pure value.

Then I think — oops, wrong.


data FileStore
= FileStore {initialize :: IO (),
save :: forall a.
(Contents a) =>
ResourceName -> Author -> Description -> a -> IO (),
retrieve :: forall a.
(Contents a) =>
ResourceName -> Maybe RevisionId -> IO a,
delete :: ResourceName -> Author -> Description -> IO (),
rename :: ResourceName
-> ResourceName
-> Author
-> Description
-> IO (),
history :: [ResourceName] -> TimeRange -> IO [Revision],
latest :: ResourceName -> IO RevisionId,
revision :: RevisionId -> IO Revision,
index :: IO [ResourceName],
idsMatch :: RevisionId -> RevisionId -> Bool,
search :: SearchQuery -> IO [SearchMatch]}

Now I think, aha, this is OO in haskell.

So, what would I want instead?

First idea: how about something like


type FileStore = [resourceName] -- pure

and then a class of RepoAble or something like that which has a bunch of pure methods that must be implemented for any concrete instance of the class. (revision, latest, retrieve, history, index, idsMatch, search)
Then you would have some unavoidably impure methods like save, delete, rename.

Concrete instances could then be defined for Darcs, Git, Svn, etc. You basically have a nice wrapper over various types of repos.

On second thought though, maybe not such a good idea. To have everything work purely after an initial fetch, the FileStore value would have to contain everything in the repo. Nah.

I just want that darned FileStore value tagged with the IO type somehow so I can tell visually when looking at the code that we’re in impure land.

This is when I realized my mistake.

Since all the fields in FileStore are functions, there’s nothing impure about it after all. If one of the fields of fileStore had a concrete value related to a repo, this would smell wrong, because we’re mixing pure and impure — but that’s not the case here.

I think the confusion for me is that I am used to seeing “interfaces” in haskell defined in terms of implementation of a type class, but here the interface is just the arbitrary fields of a datatype, which I think is a bit less type safe.

So, I still think FileStore could be improved that way by taking advantage of typeclassing, but it’s not a matter of it being impure like I initially thought.

Oh boy howdy! Patch-tag just got a bunch of new features.

For starters, we have repo browsing built on gitit. This may sound like an easy thing to do, and we sure thought it would be before actually doing it, but it turned out to be quite a chore. Gitit has some memory issues, and no user permissioning model whatsoever. But we duked the memory issues out with the haskell profiler, cobbled together user permissioning with some help from Benja Fallenstein, and now… it works!

Well, browsing works, diffs works, and there’s a sane repo history viewer. Still no wikis. But we’ll get wikis working soon, too, you’ll see.

You can now browse private repositories with gitit too.

Also pushed:

Better error handling for emails, so hopefully no more severely belated registration emails.

Repo view is better.

You can no longer delete a repo by accidentally clicking the delete link. It’s now a submit button, and even that has a nag screen that tries to convince you that repo deletion is a Bad Thing.

Did I forget anything?

Oh, we ended phase wild alpha: unlimited users may now sign up.

Finally, some bad news for our few 1 users… you know who you are, you all got emails. It’s official now. We are phasing out Darcs 1. Existing darcs 1 repos still work for now, but we turned off creation of new darcs 1 repos, and are encouraging… well, forcing, everyone to move to darcs 2. In a bit — don’t worry, there’s still time. On the plus side, darcs 2 is better than darcs 1 in almost every way, so you should actually send us flowers and candy for twisting yalls arms. In all seriousness, dropping Darcs 1 was a tough call but we are being realistic. We have very ambitious plans for patch-tag, and serving multiple versions of darcs just seemed like something that would bog us down that very few people actually used, and the ones that did use it arguably shouldn’t be. To enjoy a beautiful garden, one must sometimes prune.

So, anyway — behold the new and improved Patch-Tag.

Enjoy!

To provide a wiki editing mechanism for repositories in Patch-Tag — which should eventually work for both darcs and git repos — we are adopting Gitit to our purposes by adding a security model with read and edit permissions for wikis, and making it posible for gitit to host more than one wiki at a time.

Overall development is proceeding smoothly, but one decision I regret is having used ImplicitParams for global-ish variables in the first version of our tweak.

ImplicitParams are evil!

They are evil in the same way that global variables are evil. It’s tempting to use them, because they seem to reduce some types of boilerplate. But it just takes a very few steps along that path before understandability becomes seriously impacted.

In fact, one of the best explanations i have seen of ImplicitParams (which actually argues for their goodness) is that IPs make it possible to have global variable-like behavior in haskell without using IOrefs, or other less tractable haskell98 solutions.

But when I look at the way we are using ImplicitParams in our gitit tweak, I am concluding that we shouldn’t be using IORefs *or* ImplicitParams, and basically should be staying away from globals altogether.

The bits of our program that are global-ish — basically configuration information for wiki requests and template key-value information for wiki display — should just be passed as a normal argument to the functions that need it. It’s a bit more wordy, but it tags every function that uses “global-ish” variables clearly, and I’ll take a big increase in understandability for a slight decrease in conciseness.

Exhibit A:


type ParamsHandler = (?params :: Params) => Handler

withMessages :: [String] -> ParamsHandler -> ParamsHandler
withMessages msgs val =
let ?params = ?params { pMessages = msgs ++ pMessages ?params }
in val

I look at this, notice that val doesn’t use anything defined in the let clause, and my brain shuts down.

Without implicit params:


withMessages :: Params -> [String] -> (Params -> Handler) -> Handler
withMessages params' msgs hndlr =
let params = params' { pMessages = msgs ++ pMessages params' }
in hndlr params

Maybe it’s just me, but I find the latter version much easier to understand.

Does anybody use git or darcs for versioning anything other than source code?

Personally, I version resumes and job applications, pictures of myself for quick avatar uploading (this is not all that clever given the alternatives of flickr / picassa, it’s just something I fell into), and craigslist postings for private purposes such as room rentals.

I guess it gives me peace of mind to be able to go back to an earlier version of something I was working on, regardless of whether it’s in a computer language or a human language. Am I weird?

My partner Matt pointed something out this evening that I had understood on a gut level for a while but never really articulated.

I still have the centralized version controlling mindset, from years of using subversion and (occasionally) cvs.

Really the only reason I switched to a dvcs from a cvcs is the luxury of making commits offline and pushing them when I have connectivity. And really the only reason I like making commits offline is that sometimes I have to literally pull out my network card to get any work done versus spend six hours reading reddit. Well, that and the fact that I like haskell, and darcs is the version controlling system of choice for haskell hacking — though there has been a marked shift lately to git. Time will tell on that.

But other than being able to work offline, my workflow hasn’t really changed. I check out from my centralized repository, which is on patch-tag. I make my changes, commit, and push.

This is sad, when I compare my workflow with, say, the development maelstrom that surrounds the linux kernel. Linus *really* take advantage of using a distributed version control — git, in this case. Linus has his twelve apostles, or whatever they are called, the trusted committers that he pulls from. The apostles have their guys that they trust, and so on out to the cubicle jockey in a data center in outer Mongolia that has only fixed one kernel bug in his life because it bit him in a weird way that affected only him. The fact that Mr. Mongolia’s patch still manages to filter in to Linus eventually through the nested circles of distributed trust is one of the wonders of our world, and a reason I am glad to be alive in this day and age.

But it is so not me.

It’s like that motivational poster that says that 99% of people only use 10% of their brain power. Exactly. I probably only use 2% of the awesome power of distributed versioning — the part that lets me work offline, to be precise.

I don’t branch promiscuously. There’s the production branch for patch-tag and the dev branch, and that’s it. And of all my projects, so far patch-tag is the only one I have felt the need to branch at all.

On the rare occasions when I have to merge my blood runs cold, even though darcs’s cherry picking features usually make merges quite easy compared to my experiences in cvs and svn land. Come to think of it, merging wasn’t even that bad when I was using a centralized vcs. I’m basically just a worry wart that is easily frightened.

It’s almost embarassing.

For a guy basing a business on providing better access for a cutting edge version controlling system (darcs) written in a cutting edge webramework (happstack) in a cutting edge language (haskell)… I guess I’m not really that cutting edge.

Follow

Get every new post delivered to your Inbox.