Sunday, December 28, 2008

Fish in Monk's Clothing

"Merry Christmas! Could you come to the kitchen and help with the fish?" It wasn't exactly unexpected, but it was still a nice little challenge, like Top Chef the home edition. Unfamiliar kitchen, lots of competition for space, no specific instructions and the opportunity to make or break someone's Christmas dinner. On such occasions, it's good to have a little bit of wisdom from Julia Child in your back pocket.

My travel plans to Illinois had been delayed for two days by snow and ice, so I ended up flying on Christmas day, getting to my brother's house about an hour and a half before guests were showing up for dinner. Everything on the menu was traditional in that household except for the fish, which my brother doesn't eat, so I got volunteered to cook that.

Again, I did have some warning. Several days before, my brother had mentioned on the phone that some guests had asked for fish instead of tenderloin, and that he had bought some frozen tilapia filets. All he needed was a recipe. I said that for simple white fish, I used to like the method that Julia Child had gotten from some monks in the south of France, an episode entitled ``Fish in Monk's Clothing,'' where the fish is baked covered in lots of aromatic vegetables. "Search on the internet, I'm sure you'll find a recipe," I said.

Well, he had searched and had found four recipes for tilapia, but none were Julia's. I didn't like the look of them and although I hadn't made this dish in years, I preferred to find my own way again. Fortunately, the dish turned out well, but the down side was that I had no recipe to give to the people who asked for one, only a bunch of vague constraints.

The essential thing is that the mix of vegetables should taste good, but be reasonably mild so as not to overpower the fish, and should still have a lot of moisture in it. You need enough to cover the fish reasonably well. The vegetables drip flavor into the fish while at the same time protecting it from losing moisture in the direct heat of the oven.

(For the Haskell readers, think of the following as a sort of QuickCheck test suite for the actual method.)
  1. Chop and saute a bunch of aromatic vegetables, season with salt and pepper, thyme or other mild herbs, and reduce with some white wine. The vegetables should be soft, but still very moist and it's good to have some liquid remaining.
  2. TASTE the vegetables. If they don't taste good, fiddle with the seasoning until they do.
  3. Season the filets with salt and pepper, then place on an oiled baking pan. If the tails of the filets are much thinner than the main part of the body, overlap them so that the fish is roughly the same thickness all over.
  4. Layer the vegetables over the fish along with any remaining liquid.
  5. Bake gently until the fish is just opaque and flakes easily. I think we did 350F for about 15 minutes, but this will vary with the amount and size. You could also microwave it for 5-10 minutes, covered, if you use a glass or porcelain casserole dish.
As for which vegetables, that varies based on what I have on hand, but start by sweating an onion in olive oil and butter, then adding celery and a few chopped cloves of garlic. It is fine to brown the onion a bit, but not the garlic. This time we added some chopped mushrooms and parsley. I have added carrots in the past, but that's about as strong as I would go. Julia Child used a head of iceberg lettuce chopped up, but I've never had the nerve to try that. Spinach or swiss chard make a nice choice, but kale, mustard greens and cabbage are too strong. Fennel is a nice addition if you like anise flavor.

Any simple white fish works here, such as flounder, sole, tilapia, catfish, etc. I think I've done it successfully with bluefish, but I would avoid salmon.

How close this is to what Julia Child did, I really don't remember, because I only saw the show once long ago, but I'm pretty sure I've got the essence right. It's a simple way to marry fish with whatever vegetables are available. In any case, it was good enough for Christmas dinner.

Sunday, December 14, 2008

The Pattern of Walking

These images may look like Christmas lights, but they were created simply by holding a camera on long exposure while walking on the beach at dusk. If you just wave the camera around, the patterns are uninteresting, because they have little cohesion, but just walking straight created unexpectedly interesting results.

They remind me of high school physics, when we learned about cycloids by attaching a light to a bicycle tire. The walking images are more regular than I expected, but also far more convoluted than a cycloid. Just as the hidden motion of the tire was revealed in that experiment, these images must show something fundamental about walking. I'm just not sure what.

Monday, November 17, 2008

Monday, November 10, 2008

Functional Programming and the Universe

In Lee Smolin's TED talk How science is like democracy, he describes how our understanding of space and time has evolved. He describes three stages of cosmology:
  1. Aristotelian, which is hierarchical and all properties are defined with respect to that hierarchy;
  2. Newtonian, where properties are all defined with respect to an eternal absolute background of space and time;
  3. Quantum Theory or Relational Universe, where the universe is nothing but an ever evolving network of relationships, and all properties are about relations between subsystems.
Two quotes from the talk that jumped out at me:
According to Newton, space is just the way that god knows where everything is.
And this one, regarding the modern relational model of the universe:
Space is just one aspect, so there's no meaning to say absolutely where something is, there's only where it is relative to everything else that is, so we call it a relational universe.
In other words, even the physicists don't use an object-oriented model to describe objects any more.

Friday, October 31, 2008

Halloween Slideshow

As a public service, I've made a Halloween slideshow out of photos I've taken over the last year. Comprising over a hundred scary, ghoulish and horrifying images, you can set it playing on a spare monitor and be frightened all day long.

Tuesday, October 14, 2008

Pie Night

My friends Michael and Susan have a wonderful tradition that grew out of growing too many pumpkins.








Pie night.








They make 10-15 pies, everybody brings a pie, everybody eats pie until they can't eat no more.


And then we have pie for breakfast.

Monday, August 4, 2008

Two-dimensional zip

I've been doing battle with things like CSS recently (the W3C will be first against the wall when the revolution comes,) so it was a pleasure to run into a little Haskell puzzle and an elegant solution.

I was working with a matrix represented with a list of lists: [[a]]. I wanted to add the row and column indices to each element, giving: [[((Integer,Integer),a)]].

This isn't a pattern I remember seeing before, but it seemed simple enough, so I just hacked away. Here's my first try:

> index grid = zipWith indexrow [0..] grid
>     where indexrow rn rs = zipWith (\cn r -> ((rn,cn),r)) [0..] rs

Serviceable, but neither pretty nor general. The one dimensional case is so elegant; for any list, you can add indices with:

> index1d xs = zip [0..] xs

The zip function is simple and the infinite list of indices covers all cases. So it occurred to me I was looking for two things: a two-dimensional version of zip; and a grid of index tuples, semi-infinite in both directions.

Both turned out to be simple enough. Here's the grid of tuples using list comprehensions:

> indices2d = [[(r,c) | c <- [0..]] | r <- [0..]]

And the two-dimensional zip:

> zip2d = zipWith zip

And it's easy to reproduce the "With" version:

> zip2dWith f = zipWith (zipWith f)

So now my function looks like this:

> index2d grid = zip2d indices2d grid

or just:

> index2d' = zip2d indices2d

This version is clearer, simpler and easily generalizable to higher dimensions.

Thursday, May 29, 2008

Eschewing flip

I realized recently that I've developed a small dislike of the Haskell function flip, which reverses the order of arguments of a binary function:
mod 3 5 ==> 3
flip mod 3 5 ==> 2
flip is generally used in place of a lambda expression, when constructing a specialized function:
map (\x -> mod x 17) [1..] -- with lambda
map (flip mod 17) [1..] -- with flip
Unfortunately, my brain really doesn't like that reversal. When reading any non-trivial expression using flip, I have to stop and think about which argument is now where.

I've found that I prefer sections. You need to have one of the arguments handy, but I find that's often the case:
map (`mod` 17) [1..] -- with section
I like this form better because it preserves the visual ordering of the arguments, which seems to be deeply seated in my reasoning process. Because of Haskell's flexibility with switching between prefix and infix application, it's easy for me to adopt a style to suit this preference.

Tuesday, May 13, 2008

Paul McCartney was in a band before Wings?

Jeremy Shaw observed today that "Haskell is moving up in the world." His evidence was that a Google search for "haddock" now puts the Haskell documentation tool third on the list.

I guess we'll know that Haskell is a complete and total success when we overhear some kid in a supermarket asking, "Haddock is a fish?"

Wednesday, February 13, 2008

Rewinding the Mind

Jeremy Shaw sent me this bit about a DVD rewinder. Very humorous, of course, but there's also a nice little moral about programming in there.

When I was at Linspire, we often got questions from people looking to switch to Linux for the first time: How do I defrag my disk? Where do I buy anti-virus software?

We would explain that Linux filesystems didn't need defragmenting and that the virus problem was virtually non-existent. But sometimes, there was just no reassuring them. IT people sometimes said they simply had to have virus protection software, bought and paid for, because the company had made it mandatory for all computers. We felt a little silly, but we licensed one, shipped it and then they switched.

I wonder how many people learning a functional language wondered how to allocate and deallocate memory like they did in C? Whether the answer is obvious or not depends on one's understanding of the semantics of the language. If you have a model of C semantics in your head and you're looking at Haskell code, you're predictions about what's going to happen are bound to be wrong.

All these are examples of essentially the same problem. If we can't see (or otherwise sense) how a technology works, then a change in the underlying mechanism will leave us confused because our mental models are out of date.

I tend to prefer designs that show a technology at work, such as record players as opposed to most CD or DVD players. Unfortunately, miniaturization and digitalization only make the problem worse. I suppose that's why Hollywood always has been at the forefront of computer graphics, because the audience has no idea what's going on without all the flashing lights.

I will pursue these ideas further in some upcoming posts about functional programming and user interface design.

Thursday, January 31, 2008

The Programming Grapevine

Two non-Haskell programmers from Linspire went indoor rock climbing last night. One was wearing a Firefox t-shirt and someone next to him asked if he worked for Mozilla. He explained that he actually worked at Linspire, to which the guy said, "Oh, you guys use Haskell there, don't you?"

It's nice to know that the word has gotten around.

Well, David Fox and I left last summer and Jeremy Shaw has one foot out the door, so the Haskell presence at Linspire is just about over, but we continue to use and maintain many of the tools and libraries we built there. David and Jeremy have been cleaning up the version number policy in the Debian package builder (called the autobuilder) so that we can build Debian repositories of Haskell software. There is still some work to do, but you can look at our darcs repositories to see if there is anything that might interest you.

To see what we're up to now, see Section 7.1.6 of the Haskell Communities and Activities Report.

Monday, January 14, 2008

Even a blind chicken finds a kernel of corn every once in a while.

Translated, that means, if you take enough walks at sunset and snap enough photos, eventually you will get lucky. I took this photo this evening at Windansea beach in La Jolla:


No, it's not just a nice sunset. I mean really lucky. Look at this closeup of the left center of the image:


That dolphin jumped only once that I saw. I just happened to press the shutter at the right time.

If only I'd been using a real lens. The little 4X zoom lens on my Canon A630 is really at the edge of its range here.

Mebbe

My friend David has always had a knack for brevity and wit, the most recent example being this snippet of Haskell:
mebbe x = maybe x id
Not as clear as fromMaybe, perhaps, but much funnier.

Sunday, January 6, 2008

I visited New York City at Christmas time, attending the Christmas Eve service at All Souls Unitarian Church, which I attended regularly growing up. I don't attend any church regularly, but if I did, this would be the one, as the ministry and congregation have a very open, rational, and gentle approach to religion. Even so, my mind generally wanders during the prayers because I find them a bit bland. My ears perked up this time, though, when Forrest Church said: "Want what you have; Do what you can; Be who you are." That's a nice thought for someone who gets distracted easily by new projects.

He expanded on that idea later in the prayer:

And let us do what we can,

Not climb every mountain,

But, dismissing pipe dreams,

Climb one splendid mountain,

Doing—not less than, not more than—but precisely what we can,

That our life may be filled with attainable meaning.

In the light of the new year, it seems a bit bland, but I guess that's the way of prayers: they resonate with your emotions. I was decompressing from my pre-Christmas rush to complete some projects and this caught me like a rogue wave. Here's the full text of the prayer.