[Haskell-cafe] Re: Bathroom reading

Albert Y. C. Lai trebla at vex.net
Fri Aug 17 21:59:26 EDT 2007

Dan Weston wrote:
> I hate to be a party pooper, but isn't this just:
>  > f = foldr (\a z -> (a:snd z,fst z)) ([],[])
> This takes less time to grok and takes no longer to run.

For each type with exported constructors, one can always write 
deconstructors for it, if not already found in libraries. One may then 
argue that ~ is never necessary. Given

f ( ~(Left (z0,_)) : Right ~(Just z1) : xs ) = (z0, z1, xs)

you can always hand-compile to

f (x0 : Right y1 : xs) = (fst (getLeft x0), fromJust y1, xs)

But ~ is desirable:

0. Which version is easier to understand?

That is a bit subjective, but I think it comes down to this. (As do all 
debates over whether concise notation is readable, really.) To a kid who 
has not learned the word "arctan", I have to say, "draw this 
right-angled triangle, with this side being length 3, that side being 
length 4, now measure this angle, that is what I mean by arctan(3/4)" - 
you know, all the details, step by step, hand in hand. To a learned 
adult, I can just say, "arctan". In fact, if I spelt out the details to 
the adult, step by step, hand in hand, he/she would think I'm 
condescending or counterproductive.

Specifically in the case of ~, it makes transparent the structure of the 
data to be expected: By just reading one spot, you see it wants a list 
of two or more items, the first item is a Left, in which there is a 
tuple, the second item is a Right, in which there is a Just.

That same information is torned apart without ~: part of the information 
is on the left, and the rest is hidden on the right to be recovered from 
the deconstructor calls and re-constructing the picture in your head. 
This is because it is more low-level. The "what" is encoded beneath the 
"how". You follow the code execution and then you reverse-engineer its 
purpose. It is quite attractive when you have no notation to denote the 
purpose. It is a poor choice when you have a notation to denote the 
purpose: "what" data parts are wanted, and "when" they are wanted, 
without reading a single function call, the "how".

1. Which version is easier to change strictness?

Strictness and non-strictness are tricky to get right for performance or 
even mere feasibility. An important programming activity is 
investigating various levels of strictness. It is imperative to be able 
to change strictness efficiently.

~ is already a non-strictness annotation. Anyone who already understands 
the ! strictness annotation understands this one too. By just toggling 
~'s you toggle non-strictness. It's that easy to change.

Here is the function again. I'm going to change its strictness.

f ( ~(Left (z0,_)) : Right ~(Just z1) : xs ) = (z0, z1, xs)

I now want the second cons to be later, the Left to be earlier (at the 
same time as the first cons), the tuple to be later, the Right to be 
later (even later than the second cons), and the Just to be earlier (at 
the same time as the Right). I can do that by just toggling ~'s:

f ( Left ~(z0,_) : ~(~(Right (Just z1)) : xs) ) = (z0, z1, xs)

Without ~, much more change is necessary. Here is the non-~ code before 
change again:

f (x0 : Right y1 : xs) = (fst (getLeft x0), fromJust y1, xs)

The change is:

f (Left y0 : xs) = (fst y0, fromJust (getRight (head xs)), tail xs)

Both sides have to be changed. On the left, the data structure has to be 
changed. On the right, the function call structure has to be changed. 
You have to remove a constructor on the left and add a deconstructor on 
the right, or add a constructor on the left and remove a deconstructor 
on the right. This is a dream come true for IDE marketeers. This code 
manipulation is too annoying to be done by hand on a daily basis, yet 
mechanical enough to be done by software easily. A marketeer can sell an 
IDE plugin for this and garner much money and gratitude from 
unsuspecting programmers, capitalizing on the fact that some languages 
do not provide an annotation to trivialize this whole business, and in 
those that do, some programmers refuse to use it.

More information about the Haskell-Cafe mailing list