Sententia cdsmithus

June 4, 2008

Some video talks on programming topics

Filed under: Uncategorized — cdsmith @ 7:51 pm

Last Thursday, I attended a meeting of the Colorado Springs Open Source Meetup Group. I ended up offering to record and post videos of the presentations. They are now available. Matthew McCullough’s presentation on JavaFX is here, and Scott Ryan’s presentation on jQuery is here. I should mention that I had absolutely nothing to do with either of these presentations, except that I showed up with the video camera and microphone. This was a test run for recording my presentations at C-SPLAT (the Colorado Springs Programming Languages and Tools interest group) next week. So as far as content goes, I take no responsibility for inaccuracies or unusual views expressed in the talks.

As test runs go, all was pretty smooth. The biggest problem was that Google Video has been having some problems, and took most of a week to actually make the videos available for viewing after I uploaded them. Also, Google’s processing reduced the quality to the point that you can’t easily read the presentation slides. Next time around, I might see about seeding them in BitTorrent as well as uploading to Google Video; and of course I’ll make my slides available in PDF alongside the video.

Web Site Issues: Resolution

Filed under: Uncategorized — cdsmith @ 7:50 pm

Well, after the catastrophic failure of my web site earlier this week, I’ve put everything back at http://www.pphsg.org/cdsmith.

In case you’re wondering, the PPHSG is a group I started in 2001 to organize science and math education activities for home-schooled children. At the time, I had a neighbor who was home-schooling. The PPHSG still continues to this day, but I’ve passed on leadership to some actual home-schooling parents who have decided not to use the web site. So voila, instant replacement personal web site!

May 17, 2008

The Best Nigerian Scam Email Ever

Filed under: Uncategorized — cdsmith @ 10:39 am

I just received this email. The irony is great.

Subject: SCAMMED VICTIM COMPENSATION

Rev.Dr.Abraham Newman
Regional Director to Nigeria
International Drug and Terrorist Enforcement (IDTE)
United Nations Office,3 Whitehall Court
SW1A 2EL London U.K
Phone:+44 7045767393
Email: infoidte@yahoo.co.uk
Alt.stben09@gmail.com

Good day,

This is to bring to your notice that I,Rev.Dr.Abraham Newman, United Nations Regional Director to Nigeria representing the International Drug and Terrorist Enforcement (IDTE) has been appointed by United Nation/International Financial & Economic Crime Unit to Nigeria in association with AFRICA DEVELOPMENT BANK to pay 150 scammed victim’s the sum of $1000,000 USD (One million Dollars) each. You have been listed and approved for this payment as one of the scammed victims to be paid this amount in the second phase of the Economy Reform Project; I would like you to Provide/confirm your detail, so that your compensation would be paid out to you. Get back to me as soon as possible for more details on the immediate payments of your $1000, 000 USD compensations/Beneficiary funds.

According to the number of applicants at hand, 114 Beneficiaries has been paid, Most of the victims are from the United States while the rest are Europeans and Asians, and we still have more 36 left to be paid the compensations of $860,000 USD each. Your particulars was mentioned by one of the Syndicates who was arrested in Lagos, Nigeria as one of their victims of the operations, you are hereby warned not to communicate or duplicate this message to him/anyone for any reason what so ever as the Interpol is already on trace of the criminal. So keep it secret till they are all apprehended.

Other victims who have not been contacted can submit their application as well for scrutiny and possible consideration.

You can receive your compensations payments via ATM CASH CARD. I shall feed you with further modalities as soon as I hear from you.

Yours faithfully,
Rev.Dr.Abraham Newman
+44 7045767393

May 6, 2008

Why licenses don’t matter (and why they do)

Filed under: Uncategorized — cdsmith @ 3:04 pm

There’s a fairly long history in the free software and open source communities of being very interested in licensing. It’s always been ironic to me, since free software is supposed to be about not exercising control over how people use your software. Most recently, I read this article on whether the GPL can be “revoked” on a project to which it has already been applied. There are any number of other issues: Can this library be used by that project? Can I relicense your code to a less permissive license without making any substantial changes? And so on…

I am of the opinion that the legal meaning of a license is completely irrelevant. It doesn’t matter what someone has the legal ability to do. It’s necessary to pay attention to the social influence and intentions of others.

Example : MySQL

Let me make the point by giving an example. In fact, there’s one example that covers this very well. Think about MySQL, the database company. Yes, they are most definitely a company, with all the overriding profit motive that implies. Profit motive isn’t bad; but it is a motive that might not align with your best interests. They wrote this database, and released it under the GPL. It made a big name for itself by being a “free” database. In fact, at least until very recently, it was a really crappy database that couldn’t do basic stuff like transactions or handling reasonably complex SQL; the only reason you’ve ever heard of it is that it is “free”. But it’s also dual licensed as a commercial database; and here’s the rub: ultimately, the GPL nature only matters if MySQL wants it to matter. They let it matter when it means free publicity and a cult following; but when they see the opportunity for a profit, the GPL suddenly seems to grant you a lot fewer rights that you thought it did. The legal and semantic machinery going on is rather elaborate; but it is not the point. It’s only the excuse. What it comes down to is this:

  1. MySQL can afford to hire a lawyer, and you probably can’t.
  2. People accept MySQL as the expert on what “their” license means.

What this means is this: if you use MySQL, you accept that you are at the mercy of MySQL’s whims. If they decide you should give them money, you give them money. In fact, it goes further than that. As a test, some years ago, I approached a MySQL representative by email about one of the more peculiar and ridiculous re-interpretations of English words that they put forth. In particular, I asked this. Suppose I had an application (not free software itself) written in Java using JDBC; and that I distributed it with PostgreSQL, but since the application just uses simple SQL and JDBC, someone who uses my software might conceivably download MySQL and use that instead. In fact, suppose I have customers who I suspect have done just that, since they prefer the administration tools for MySQL. The response was a rather obtuse legal threat: something like “We can’t give you legal advice, but it’s always safest for you to buy a license. The protection you get will be worth the investment.” They want me to buy protection. To bastardize a line from a Patricia Briggs book: And yes, just like the mafia, MySQL only protects you from themselves.

So if you have a free software application and the company doesn’t see any other reason to make a threat, then you may use MySQL. But the other rights in the GPL are lost. If you download MySQL and it interacts with some other (possibly non-free, possibly threatening to MySQL) application using publicly specified interfaces, MySQL feels they have the right to sue someone. If you modify MySQL and try to distribute your changes, who knows what would happen? And don’t imagine for a second that you could get away with forking the code, which is in the end the most fundamental free software right. If you had any success, there would be lawyers knocking on your door before you could sneeze.

Lessons from the example

So this is the situation we’re in. You may have legal rights granted to you by a document like the GPL (or BSD, or MIT, or Creative Commons, or…) But because some other party holds some kind of power over you, you can’t really trust your ability to exercise those rights reliably. Of course, there are many kinds of power involved here. Not everyone is motivated by profit. Some people are motivated by social status, or even a sincere desire to do good. Power might include:

  1. Financial power. You can’t hire a lawyer, a company profiting from their software can.
  2. Presumed authority. Since the software provider chose the license, people take their word on what it means. This is regardless of the fact that in the free software world, virtually no one except major figureheads actually writes their own licenses.
  3. Social expectations. Even if I can get away with doing something that the author of the software doesn’t like, if they are going to be upset my it I’ll probably take a pass. It would take a definite jerk to ignore the wishes of the person who did all that work and made it freely available to you.

But whatever the kind of influence being wielded (and some of those kinds of influence are not entirely bad) the fact remains that you can’t tell everything about your ability to use software by the written license.

What now?

So how did we get here? What do we do?

I think how we got here is that we’re computer programmers. Computer programmers, by nature, tend to look for simple and unambiguous rules that define what is possible. The license pretends to be that, and we miss that it’s a false set of rules. It’s a set of rules only in theory, in an idealized sort of half-egalitarian, half Ayn Rand world, where everyone acts in their own best interests and has an equal understanding that others will too, and everyone is on equal footing in terms of the power they have to act in those interests. Legal absolutism simply doesn’t translate into the real world, as much as we’d like to see it happen.

Instead, we need to realize what people have known since the beginning of time - but we’ve tried to forget. It matters who you are dealing with. We should take the time to find out the motivations of the people who build the things we use. In particular, there are different kinds of groups of people building free or open-source software. At least a few of them are as follows. (Of course, I’m grabbing archetypes that no one will meet exactly. There’s no intention that you can’t span a few of these groups.)

  • Commercializers. These are people who completely believe in their ability to turn a profit by building open source software. They are often the dual-licensers, GPL+commercial, or sometimes the support sellers, or sometimes the people who build service businesses and use their software to provide those services. In any case, the open source side is likely to use the GPL or a similar restrictive license just to stop the competition. In its purest form, this sort of group doesn’t care about you unless you are making them a profit. Maybe you’re actually paying them. Maybe you’re getting your customers to pay them. Maybe you’re giving them positive reviews and claims of popularity that they can use to take other people’s money. Just make sure your intentions don’t conflict with their commercial interest. This is the most dangerous group, as business sorts tend to believe it’s a perfectly normal “strategic decision” to make other people miserable.
  • Idealists. Some groups are motivated by the pure idea that software should be free. This certainly includes the entire GNU organization, and a number of others to boot. The GPL license is pretty popular here. The motivation is to make more software free. If you aren’t building free software, this might be a good time to ask yourself if taking advantage of these people’s work is the right thing to do. On the other hand, very few people are really extremists here. No one is going to hate you for using gcc to compile and build closed commercial software; but you might be careful if the project is newer, and particularly if it’s a library licensed under the GPL, which is a clear sign that the authors don’t want you to do that. (The legal meaning doesn’t matter; it wouldn’t be okay to use readline in a commercial product even if it turns out the license is unenforcable.)
  • Social Groups. Often, free software is built by groups who are just having fun. They want to develop ideas, work with other people, but avoid having obligations to customers or dealing with business concepts like marketing, payroll, etc. Most of these groups will license software under the BSD or another very permissive license. In less software-oriented groups, Creative Commons is also popular here. They don’t care what you do with their software, so long as you don’t try to keep them from doing as they please. Many groups of this form will be happy to hear that you are finding their software useful. The biggest way to piss these people off is to adopt an attitude of entitlement. If you avoid that, you’re fine.
  • Academics. This last group is interested in writing the software for the sake of writing it, learning what they can from it, and moving on. They will be thrilled if you use their software to solve other interesting problems. (And I mean interesting in the academic sense.) If you just have fun, they won’t mind. If you commercialize it, expect an attitude of profound apathy. There are academics who are interested in commercializing their work, but they don’t release their software with free licenses. Most academic work tends to be released under BSD, MIT, or similar licenses. In fact, it’s worth noting that both of those licenses are named after the major universities where they were originally written.

Licenses matter after all

While I started this rant by saying that licenses don’t matter (in terms of the legal rights they grant you), it turns out that they actually matter quite a bit (because it helps you tell what kind of group you’re working with). This is important for using a project. It’s also important for getting involved in a project.

Here’s a true story. A few years back, I got involved in a group that was building libraries for C programming on an embedded device. I write a lot of code for dealing with an LCD controlled, and built a graphics library and a user interface library on top of that. Then one day, someone wanted to use our libraries to write a commercial application for these devices. There followed a massive debate, wherein I realized that I had completely different goals than anyone else. I’d just been having fun. Others were talking about setting up a commercial dual license, deciding how to apportion the profits; or else insisting that we had built this to encourage free software, and we shouldn’t just give it away to people who would make money on the backs of our efforts.

The project had been licensed under the GPL. In retrospect, I should have asked more questions about that before I got involved. I just assumed it was the easy default choice, since it’s the license more people have heard of. It turns out that some people in the project thought it mattered quite a bit. Lesson: the license is a good way to get an initial idea of the kind of people you’ll be working with in a project.

Anyway, that’s my rant.

May 4, 2008

Solving a Logic Problem with Coq

Filed under: Uncategorized — cdsmith @ 10:48 am

I’ve been playing around with the Coq proof assistant tool over the weekend. Here’s an interesting problem and its solution proven with Coq. I am by no means an expert in this. I’ve used Coq for less than 6 hours at this point. There are a lot of nicer tutorials out there, including the one on the Coq web site. But this is an interesting motivating example, and I’m writing to share my experiences.

The puzzle I’ll solve here comes from John Pratt’s page. A lot of supposed “logic puzzle” sites aren’t really logic puzzles at all, but just plays on words; but that one is okay. Here’s the puzzle:

When asked her 3 children’s ages, Mrs. Muddled said that Alice is the youngest unless Bill is, and that if Carl isn’t the youngest then Alice is the oldest. Who is the oldest and who is the youngest?

The first step is to start up Coq. In my case I’ve generally used CoqIde, which is a simple apt-get in Ubuntu. However, for this blog post I’ll use the command-line coq-interface in hopes of more portability. Let’s tell Coq a few of the basics of the problem, such as that there’s a domain of discourse, and it has three children in it named Alice, Bill, and Carl.

Section Ages.
Variable Child : Set.
Variable Alice : Child.
Variable Bill  : Child.
Variable Carl  : Child.
Variable Youngest : Child -> Prop.
Variable Oldest   : Child -> Prop.

The last two lines declare unary predicates for the domain of discourse, indicating whether a child is the youngest or the oldest. Unfortunately, Coq doesn’t know some things that we’re assuming here. One such fact is that the three children are different from each other. So let’s tell it that.

Hypothesis Diff1 : Alice <> Carl.
Hypothesis Diff2 : Bill  <> Carl.
Hypothesis Diff3 : Alice <> Bill.

Each of these hypotheses has a name, so that we can refer to it in the proof later.

Next, there’s some implicit meaning in the superlative words “youngest” and “oldest”.

Hypothesis Superlative1 : forall A B, (A <> B) -> Youngest A -> ~Youngest B.
Hypothesis Superlative2 : forall A B, (A <> B) -> Oldest   A -> ~Oldest   B.

In other words, you can’t have two different children who are both the youngest or the oldest. Even twins are usually born a few minutes apart!

Finally, “youngest” and “oldest” are opposites. Since there is more than one child, no one can be both.

Hypothesis Antonym1 : forall A, Oldest   A -> ~ Youngest A.
Hypothesis Antonym2 : forall A, Youngest A -> ~ Oldest   A.

Having now explained the terminology to Coq, we may now enter the information given by Mrs. Muddled in the problem.

Hypothesis Given1 : ~ Youngest Alice -> Youngest Bill.
Hypothesis Given2 : ~ Youngest Carl  -> Oldest Alice.

Now that Coq understands the premises, we need to tell it what we are proving. That requires solving the puzzle. Simple enough: Alice is the youngest unless Bill is, which means Carl can’t be the youngest. But if Carl is not the youngest, then Alice is the oldest, which leaves Bill as the youngest. So the youngest is Bill, the middle child is Carl, and the oldest is Alice. Let’s tell Coq that.

Goal Oldest Alice /\ Youngest Bill.

And Coq responds by listing the goal, and all the hypotheses we may use to prove it:

1 subgoal

  Child : Set
  Alice : Child
  Bill : Child
  Carl : Child
  Youngest : Child -> Prop
  Oldest : Child -> Prop
  Diff1 : Alice <> Carl
  Diff2 : Bill <> Carl
  Diff3 : Alice <> Bill
  Superlative1 : forall A B : Child, A <> B -> Youngest A -> ~ Youngest B
  Superlative2 : forall A B : Child, A <> B -> Oldest A -> ~ Oldest B
  Antonym1 : forall A : Child, Oldest A -> ~ Youngest A
  Antonym2 : forall A : Child, Youngest A -> ~ Oldest A
  Given1 : ~ Youngest Alice -> Youngest Bill
  Given2 : ~ Youngest Carl -> Oldest Alice
  ============================
   Oldest Alice /\ Youngest Bill

Fair enough. The proof wizard doesn’t know how to solve this, so we’ll need to take it on by hand. To prove a conjunction, we can individually prove each side. Coq calls this the “split” tactic.

split.

And Coq responds:

2 subgoals

  Child : Set
  Alice : Child
  Bill : Child
  Carl : Child
  Youngest : Child -> Prop
  Oldest : Child -> Prop
  Diff1 : Alice <> Carl
  Diff2 : Bill <> Carl
  Diff3 : Alice <> Bill
  Superlative1 : forall A B : Child, A <> B -> Youngest A -> ~ Youngest B
  Superlative2 : forall A B : Child, A <> B -> Oldest A -> ~ Oldest B
  Antonym1 : forall A : Child, Oldest A -> ~ Youngest A
  Antonym2 : forall A : Child, Youngest A -> ~ Oldest A
  Given1 : ~ Youngest Alice -> Youngest Bill
  Given2 : ~ Youngest Carl -> Oldest Alice
  ============================
   Oldest Alice

subgoal 2 is:
 Youngest Bill

In other words, we’re currently working on proving Oldest Alice, but once we finish that, we’ll need to prove Youngest Bill. Well, there’s only one good way to conclude Oldest Alice, and that’s to show that Carl is not the youngest. So let’s prove the current subgoal by applying Given2.

apply Given2.

I’ll stop quoting the entirety of Coq’s responses, but here’s the important part:

  ============================
   ~ Youngest Carl

So how do we know that Carl is not the youngest? Well, it’s because Bill is the youngest. That’s rule Superlative1, but we’ll also have to tell Coq to use Bill as the other child.

apply Superlative1 with Bill.

And Coq responds:

  ============================
   Bill <> Carl

subgoal 2 is:
 Youngest Bill

So we need to prove that Bill is not Carl, and then that Bill is the youngest. (That Bill is the youngest is also subgoal 3 left over from splitting the conjunction, a fact that we’ll think about shortly.) For now, it’s easy to prove that Bill is not Carl, because that was one of our hypotheses.

apply Diff2.

And Coq responds:

  ============================
   Youngest Bill

Now it remains only to prove that Bill is the youngest. The way to go about that is to apply the first given.

apply Given1.

And Coq responds:

  ============================
   ~ Youngest Alice

This is the tricky part. The reason that Alice is not the youngest is that if she were the youngest, then Carl would not be the youngest, but then the second given statement would lead us to conclude that Alice is the oldest, which is a contradiction. Proof by contradiction, though, is generally a technique valid only in classical logic, not in the constructive logic that Coq typically uses. It turns out we won’t need to resort to classical logic for this theorem, but just to make things easier in our first pass we’ll go ahead and use it. This is one statement in Coq.

Require Import Classical.

So now having classical logic at our disposal, we can go about proving that Alice is not the youngest by applying Peirce’s law.

apply Peirce.

And Coq’s response:

  ============================
   (~ Youngest Alice -> False) -> ~ Youngest Alice

We’ll split up the implication by giving a name to the hypothesis and then proving the conclusion. This tactic is called “intro”.

intro H.

Coq responds:

  H : ~ Youngest Alice -> False
  ============================
   ~ Youngest Alice

Note that the new hypothesis is the double-negation of “Alice is the youngest.” In classical logic, which we’re now using, that’s the same as Alice being the youngest, so we’ve essentially used Peirce’s law to start the proof by contradiction. Now we’ll go backward through the contradiction argument given above. First, Alice can’t be the youngest because she’s the oldest. She’s the oldest because Carl is not the youngest. Carl is not the youngest because we’ve assumed (to obtain the contradiction) that Alice is the youngest.

apply Antonym1.
apply Given2.
apply Superlative1 with Alice.
apply Diff1.

And here’s where we are, according to Coq.

  H : ~ Youngest Alice -> False
  ============================
   Youngest Alice

This is just a double negation: a rule from the Classical package that goes by the name NNPP. Once we double-negate the conclusion, it will look slightly different from the hypothesis H, but they will actually mean the same thing. (~A is just shorthand for A -> False).

apply NNPP.
exact H.

Coq says:

  ============================
   Youngest Bill

So we’ve proven the left half of the conjunction: that Alice is the oldest. We now need to prove the right half. But wait! We already did that, as the second step to proving the left half. For now, we’ll just copy and paste the last part of the earlier proof.

apply Given1.
apply Peirce.
intro H.
apply Antonym1.
apply Given2.
apply Superlative1 with Alice.
apply Diff1.
apply NNPP.
exact H.

and Coq says:

Proof completed.

Finally, we get to say:

Qed.

Ah, we’re done. But it turns out we can improve the proof a little by using a few more Coq features: specifically, by proving some lemmas (or lemmata, if your prefer), and by eliminating the use of classical logic (since this happens to be a constructively valid statement; not all classically true statements will be, though).

First, although Peirce’s law ((~P -> P) -> P) is not true in constructive logic, but we can prove (P -> ~P) -> ~P. Let’s do so, by introducing a lemma, and then by using the automatic prover.

Lemma NPeirce : forall P : Prop, (P -> ~P) -> ~P.
auto.
Qed.

In this case, the automated theorem prover worked fine. We could have proven the theorem by hand, as well (by treating the ~P as P -> False, using the intro tactic, applying the modus ponens rule, and then easily satisfying all of the hypotheses). Using this, we can simplify our proof of Youngest Bill. The process is the same, but instead of applying Peirce’s law and the beginning and the double-negation at the end, we apply our new NPeirce lemma at the beginning, and we don’t need double-negation at the end.

Lemma YoungBill : Youngest Bill.
apply Given1.
apply NPeirce.
intro H.
apply Antonym1.
apply Given2.
apply Superlative1 with Alice.
apply Diff1.
exact H.
Qed.

Notice that I’ve also defined this as a lemma. That’s because we needed to prove it twice in the earlier attempt. May as well prove it once up front instead. So now comes the final goal.

Goal Oldest Alice /\ Youngest Bill.
split.
apply Given2.
apply Superlative1 with Bill.
apply Diff2.
apply YoungBill.
apply YoungBill.
Qed.

And we’re done. For reference, here’s the entire proof as entered in CoqIde.

Variable Child : Set.
Variable Alice : Child.
Variable Bill  : Child.
Variable Carl  : Child.
Variable Youngest : Child -> Prop.
Variable Oldest   : Child -> Prop.

Hypothesis Diff1 : Alice <> Carl.
Hypothesis Diff2 : Bill  <> Carl.
Hypothesis Diff3 : Alice <> Bill.

Hypothesis Superlative1 : forall A B, (A <> B) -> Youngest A -> ~Youngest B.
Hypothesis Superlative2 : forall A B, (A <> B) -> Oldest   A -> ~Oldest   B.

Hypothesis Antonym1 : forall A, Oldest   A -> ~ Youngest A.
Hypothesis Antonym2 : forall A, Youngest A -> ~ Oldest   A.

Hypothesis Given1 : ~ Youngest Alice -> Youngest Bill.
Hypothesis Given2 : ~ Youngest Carl  -> Oldest Alice.

Lemma NPeirce : forall P : Prop, (P -> ~P) -> ~P.
auto.
Qed.

Lemma YoungBill : Youngest Bill.
apply Given1.
apply NPeirce.
intro H.
apply Antonym1.
apply Given2.
apply Superlative1 with Alice.
apply Diff1.
exact H.
Qed.

Goal Oldest Alice /\ Youngest Bill.
split.
apply Given2.
apply Superlative1 with Bill.
apply Diff2.
apply YoungBill.
apply YoungBill.
Qed.

April 7, 2008

Code == Data: The Basics

Filed under: Uncategorized — cdsmith @ 10:36 am

There have been a lot of blog entries lately about code versus data: which is more valuable, are they the same, or maybe different, and so on. Most recently, here. That blog entry argues that code is data, and points out Turing’s work on universal Turing machines as an example. The dual argument, that data is code, can be attributed to Church, thereby completing the pair of early computer science figureheads. This won’t be new to most advanced computer science students, but I was unable to find a single place where it’s written down.

To start, two special cases will be helpful. I will be assuming that the reader knows the basic evaluation rules of lambda calculus. The technique here will be the same: use an appropriate function to represent data.

Special Case 1: Finite Enumerated Types

Suppose I want to write lambda calculus expressions to represent the four cardinal directions (north, south, east, and west), and left and right turns. Here’s what I’m shooting for, in Haskell.

data Dir = East | West | North | South
left  East  = North
left  West  = South
left  North = West
left  South = East
right East  = South
right West  = North
right North = East
right South = West

To do this in lambda calculus, I need four “data” values, and as promised they will be defined as functions.

East  := λabcd.a
West  := λabcd.b
North := λabcd.c
South := λabcd.d

(Note that I’m using := to denote definition of short-hand names; it is not, of course, part of the lambda calculus itself. In particular, you have the right to complain loudly if I try to give circular definitions; there is no such thing as direct general recursion.)

These are functions that take four parameters and return, respectively, the first, second, third, and fourth ones. Now defining functions case-wise on these values is trivial:

left  := λd.d (North) (South) (West) (East)
right := λd.d (South) (North) (East) (West)

Now the left function take a parameter d, which is itself a function, and operates by calling that function and passing it four arguments. Now if the function happens to be East, then it will return its first result, thereby correctly concluding that north is a left turn from east.

Special Case 2: Church Numerals

A slightly more involved data type is natural numbers. Alonzo Church defined natural numbers in terms of Church numerals. The idea is that a natural number n is a function which iterates another function n times on some initial value. For example, using the functions above, we can say that:

0 left North = North
1 left North = West
2 left North = South
3 left North = East
4 left North = North

So the first few natural numbers are:

0 := λfx.x
1 := λfx.fx
2 := λfx.f(fx)
3 := λfx.f(f(fx))
4 := λfx.f(f(f(fx)))

And here are a few operations on these natural numbers. It can take some hard work with a pencil and paper to see why some of them work.

inc := λp.(λfx.f(pfx))
add := λpq.(λfx.pf(qfx))
mul := λpq.(λfx.p(qf)x)

General Case: Algebraic Data Types

Algebraic data types are a general approach to defining data types in a programming language. A type may have several different forms, each of which may have several fields. Another way of saying this is that an ADT is a sum of products of other types. Here’s an example in Haskell:

data Discount = FixedAmount Double
              | Percent Double
              | Rebate Date Double

In other words, a discount is either a fixed amount of money at purchase, or a percent off the purchase price, or a rebate of some amount that happens at some future date.

Another example:

data Tree = Leaf Char
          | Branch Tree Tree

So a tree is either a leaf, or a branch node whose left and right children are trees in their own right.

Both of the special cases above are also algebraic data types. Directions have four forms, each of which is an empty product:

data Dir = East | West | North | South

Church numerals implement natural numbers defined as:

data Nat = Succ Nat | Zero

As you may guess, we’re going to write functions to represent any kind of data of any algebraic data type as a function in the lambda calculus. The idea will be this: we will ask the person using the data to write a handler for each form that the data may take. Then they’ll give us all of these handler functions, and we’ll use the one that applies. So a value of some algebraic data type will be a function that takes a bunch of handlers, and produces the result of one of them. Examples follow:

For the Discount data type, the value FixedAmount $2.75 looks like this:

FixedAmount $2.75 := λfpr . f ($2.75)

In other words, this is a function that takes three handlers f, p, and r (one for fixed amounts, one for percentages, and another for rebates). It then calls the first handler, passing it the amount of the fixed discount.

To calculate the amount of money to hand someone as they are buying an item at a price p with a discount d, one may write:

d (λa.a) (λp.(p*a)) (λda.0)

The first handler says that if the discount is for a constant amount, you give back that amount. The second says that if the discount is for some percent, you multiply it by the price and give that back. The third handler says that if the discount is a rebate to be filled later, you don’t give them anything right now. This is all done by calling the data as a function.

To use a Church numeral, you pass it two handlers. The first says what you want back if it’s the successor of another number. The next handler says what to do if it’s zero. Using this, we can write a slightly wordier version of the inc function from before:

inc := λp.p (λfx.f(pfx)) (λfx.fx)

The second handler is just a value, since there are no fields in that case.

So there you have it, not only is code a type of data (Turing’s approach), but also data is a type of code (Church’s approach).

March 30, 2008

How to Be a Jerk and Get Away With It

Filed under: Uncategorized — cdsmith @ 1:55 pm

In modern society, being a jerk has been raised to an art form. Moral offenses that would shock most of us in plain view can be excused if you know how to play your hand. Here, I cover the basics of getting away with being an immoral jerk.

Step 1: Pick on the Right Victim

The most part of successfully being a jerk is to pick on the right people. If you’re going to mug someone, you wouldn’t pick the Queen of England as your victim. You also shouldn’t go for a successful businessman or politician. Instead, choose victims with whom the general public won’t sympathize. Here are some more specific rules:

First, your victim should be poor. Rich people are trusted, visible, and most importantly have access to the press and political representation. These all work against you. It may seem like it’s better to take money from people who have it to begin with. You would be wrong. Seriously, can anyone imagine Walmart getting away with what it does if its average employees (or even customers) came from upper middle class and wealthy families? Because most of power structure in the world likes to blame poor people for being poor, and doesn’t trust them, it’s actually easier to take $100 each from 10,000 poor people than it is to take a million dollars from a rich person.

Second, your victim should be a racial minority. For some background reading on the importance of picking on racial minorities, see here. You’d be surprised what you can do without getting much attention. Modern sentiment being what it is, having Arabic ancestry is like asking to be victimized. The United States federal government has got this figured out. You may as well take advantage, too.

Whether to victimize men or women is a tricky question. The answer depends on what kind of jerk you plan to become. Although women are disadvantaged in general, you are better off concentrating on which gender that will most reinforce more negative stereotypes about themselves by resisting. If you want to do physical violence, or take someone’s children away, your victim should be male. If you want to deny someone equal pay, a job, or a leadership position of any kind, women are ripe for the picking.

Targeting children is risky, but can pay off. Stay away from children under 12, as they elicit too much sympathy from others. Teenagers, though, are demonized for for their rebellious natures and their irrational “angst”. If you manipulate the situation in the right way, and especially if you can put yourself in a position of authority (which is not too hard; even a bus driver job will do), your inexcusable behavior will be dismissed in the name of preserving order.

As you can see, there are some subtleties here. It’s worth it in the end, though. Assuming you don’t leave definite evidence of having broken the law, the only reasonable way anyone can stop you from being a jerk is to elicit enough sympathy that large numbers of people stand up to you. Choosing the right victims can almost eliminate that unlikely event.

Step 2: Appeal to Written Policy

If you played the first step well, few other people will care about your victim, but your victim will care about him/her-self. There is no more effective way to deal with such victims’ complaints than an appeal to written policy. You can even write the policy yourself, but it’s better if you can arrange to have the policy written by some nameless unidentifiable person, whom no one can blame as a result. As odd as this may sound, it will rarely occur to anyone to blame you for enforcing a ridiculous policy or failing to change it.

This is a remarkably effective strategy. Average people are very receptive to the argument that if someone doesn’t like your policies, they should have never done business with you. Strangely, this remains true when you are getting tax breaks, driving others out of business, and basically providing people with no other choices. Remarkably, it even remains true when you’re able to get the government to pass laws requiring people to do business with you.

Step 3: Blame the Victim

If you’ve still got significant opposition, then you have clearly failed to pick a victim that no one sympathizes with. No worries. You just have to stop people from sympathizing. This will get ugly, though.

Guilt by association is an especially effective tactic here. All you need to do is make enough public statements lumping your victim in with undesirable sorts, and your victim will lose all of their remaining sympathy. For this reason, it’s a good idea to drag in a few genuinely evil people, if possible. That way, you can throw the name of your real victims in the middle of a long list of terrorists, criminals, gang members, and so on. People will conclude that your victims are all bad people anyway.

If guilt by association doesn’t work, you’ll have to engage in a direct game of character assassination. Fortunately, this is easier than it sounds. Most people are not accustomed to receiving the kind of abuse you plan on giving out. They will make mistakes. Perhaps some foul language, or even violence. Maybe they will phrase something improvidently. Unless you’ve made the grave error of picking media-saavy victims, they will certainly say things in public that you can take out of context. With some care, you should be able to make sure the public hates your victim in no time at all, and any scrutiny you’re under should dry up quickly as a result.

Step 4: Use Others’ Common Sense as a Weapon

Now things are getting serious. If you can’t blame the victim, then people must have found real evidence for suspecting you. This is no time to panic, though. Most people aren’t willing to believe outrageous things, and you can use that in your favor. If what you did is completely outrageous, no one will believe your accusers, and you’ll get away free.

You are already at an advantage here, because you’re reading a web page on how to get away with being a jerk. Most people would find that beyond the bounds of common sense. But you need to go further. Never, ever, under any circumstances, should you do pick a victim who has harmed you in any way. You should also not pick a victim that you’ve publicly argued with. These things create “motive”, which helps random people believe that you are guilty. Instead, you should pick random victims, do unbelievable things to them, and then just calmly laugh and ask whether we really believe that such a ridiculous story is true.

Step 5: Tell People Everyone Does It

Now things are really bad. You have no chance of convincing people you are innocent. So what do you do? Easy: make it sound like it’s no big deal.

Here’s the idea. People are going to be angry. You can either let them be angry at you (bad idea) or you can encourage them to just be disgusted with the state of the world as a whole. To accomplish the latter, you imply that you aren’t out of the ordinary, and that everyone does what you did.

Occasionally, you may not want to be on the record as saying something that outrageous. Then a weaker form of this strategy is called for. You can merely imply that everyone does it, by unabashedly and calmly making a public statement about what you are doing. If you word things right, you can make it seem like the most natural thing in the world for you to, say, openly defy a court order.

Step 6: Procrastinate Admission of Guilt

The most important step in avoiding responsibility for your actions is to wait until no one is looking to admit what you did.

A common beginner mistake is to avoid admitting guilt at all. For small matters, this can work. If you’re being enough of a major-league jerk to reach this point, though, people will launch investigations. No, you have to admit what you’ve done. but do it on your time frame.

At this point, get a lawyer. You can be assured that any lawyer worth his salt will advise you not to talk about the case. If he doesn’t, you should specifically request it. This gives you an excuse for not commenting. Later, you can wait until media fervor has died down, and quietly admit what you’ve done once the story is old and stale. Oddly enough, the media will almost certainly play their part, holding off on the worst accusations because they can’t get “both sides” of the story. They will forget that it’s you, whether under legal advice or not, preventing them from getting your side of the story.

Should the story resurrect itself later when you make your admission, you can always appeal to the stuck in the past line to avoid talking about it then.

Step 7: Cry Terrorism

It’s your last shot. Now people are openly protesting against you in the streets. There’s only one thing left to do: call them terrorists.

[Of course this isn't serious. I am, though, looking for more links to add. If you've seen something that should be linked from here, please mention it in the comments.]

March 11, 2008

Just For Fun: Autostereograms in Haskell

Filed under: Uncategorized — cdsmith @ 1:25 pm

I’ve added some code here, which I wrote last night, to generate autostereograms from depth maps. It’s written in Haskell, but that doesn’t mean you should blame Haskell for its shortcomings.

To use:

  1. Install GHC and gtk2hs. Any recent version should do.
  2. Copy this code into a file and build with ghc --make -O2 TheFile.hs.
  3. Generate a tiling background image of your choice. GIMP’s Filter -> Map -> Make Seamless helps a lot with this, and it has some nice options under Filter -> Render to generate nice-looking images. The important thing is for your image to be seamlessly tileable, and have lots of easily identifiable points. Save it as a PNG file.
  4. Generate a depth map, on the order of about 100 x 100 pixels. (Too much larger, and you’ll have to profile and optimize my code for me.) Save it as a PNG file again.
  5. Run the program with the depth map and the background image (in that order) as parameters.

This code basically works, and realistically that’s about all I am going to do right now. There are lots of things that could be improved about it. The big three are: lots of performance issues; should be able to write out to a file instead of just the screen; and there’s something funky in the drawing that causes the depth to slope outward rather gently to each side no matter what the depth map looks like. As far as performance, the problem is with a lot of fiddling with lists for control flow; I was able to do considerably better with Cairo; but unfortunately, Cairo’s matrices only allow for affine transformations, which doesn’t seem to be quite enough to scale between arbitrary trapezoids, so the result didn’t look great and I reverted to drawing pixel by pixel. The last problem may be a rather fundamental issue in how I’m approaching the problem; but the current code works well enough to get the point.

Here are some obligatory screen shots.

Autostereogram of a LambdaAutostereogram of a Chess BoardAutostereogram of a Human

January 7, 2008

What do politics and programming languages have in common?

Filed under: Uncategorized — cdsmith @ 2:37 pm

This is a blog entry about programming languages, but I’m going to start out talking about politics.

Trigger Words in Politics

I’m currently volunteering for the Barack Obama campaign for president in the United States.  If there’s a single thing one learns quickly in politics, it’s this: ideas themselves matter a lot less than getting people to remember them.  It’s sad, because people who care about the important problems facing the government veritably thrive on those ideas.  But the other 90% of people who ultimately make the decision in the end will have trouble just keeping straight who says what.

The solution: trigger words.  Candidates express their ideas, but they always attach a word or short phrase.  The word or phrase is far too short to ever really capture any idea worth its salt; but it’s what people will remember.  So Barack Obama talks about “the politics of hope.”  He says “change” a lot.  And a good number of people will know that Barack advocates “a politics of hope” and “change” without being able to tell you what that actually means.  The words, in fact, act as a kind of subconscious repository of those ideas that people don’t mention anyway.  When Barack talks about the need to respect the dignity of people around the world instead of barricading against them as potential terrorists, he throws in the phrase “politics of hope,” and people add that to the ideas they associate with the phrase.  When he talks about banishing corporate lobbyists from the White House, or refers to his legislative work to stop unseemly relationships between members of Congress and lobbyists, he says “change” and this gets added to the meaning of change.  People remember the good feelings they had when they heard these terms before.

Of course, two can play at that game.  Since “the politics of hope” is in the end a vague term with very little meaning, it’s open for twisting and manipulation.  So it happens that, every time Barack Obama says he doesn’t think something will work, or that something is a bad idea, the response from other campaigns is “what happened to the politics of hope, eh Barack?”  And now that Barack did very well in the Iowa caucus, other candidates are scrambling to stand for “change”… but one notable exception, most of them are not talking about lobbyists and centers of political power, but rather about their own pet issues.  So it happens that one can have a spirited debate over trigger words without ever touching on actual policy differences.  Yet, one must defend one’s trigger words.  It would be ridiculous for Barack to respond that change and the politics of hope are just words and let’s forget them all; because those words are the repository of people’s good will toward the whole campaign.

Okay, yeah.  I promised this was about programming languages.  Here we go.

Trigger Words in Programming

So it was in this context that I came across a discussion across several blogs, including here and here.  I tend to agree with these authors and most issues, but I have to object that they are throwing a trigger word under the bus in the process, and that’s a serious mistake.  That word is “intuitive”.

Yes, intuitive is basically a trigger word.  People have seen languages where you have to keep looking everything up in a reference manual, or else memorize large amounts of information (e.g., Visual Basic).  And people have seen languages where things just seem to make sense (insert favorite language here).  And they prefer the latter kind of language, which is widely identified as being intuitive.  It’s a mistake to say that “intuitive” means familiar.  If anything, it means something a little closer to elegant; but I’d go for a new phrase I’m about to invent.  Intuitive means idea-efficient.  It means that there exists a small set of ideas whose straight-forward application can lead to good solutions to a large set of problems.  The principle of least surprise is, therefore, certainly a part of it.  So is the central design principle of Scheme, that “Programming languages should be designed not by piling
feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.”  In the end, though, the exact meaning of the word is something that’s experienced, not explained.  And that’s why the word itself is of such value; because I don’t want to rewrite this paragraph every time I want to mention the concept of an intuitive language.

Calling something unintuitive simply because it’s unfamiliar is a lot like saying, “What ever happened to the politics of hope, eh Barack?”  And responding that intuitiveness is overrated is a lot like responding with, “The politics of hope doesn’t matter, after all.”

So that’s my plea.  Respect the idea of an intuitive language.  Defend it, and point out that it doesn’t mean “familiar.”  Otherwise, we’re throwing away experience that could lead people to make wiser decisions about their tools.

December 9, 2007

Some Basic Stuff: The Writer Monad

Filed under: Uncategorized — cdsmith @ 11:47 am

Edit: Clarified some of the code.

Edit II: Comment about laziness.

In this post, Magnus Therning gives a number of solutions to the n-queens problem in Haskell.  The problem is just to arrange n queens on an n x n chess board so that neither is threatening any of the others.  It’s a classic problem that’s solved with backtracking.  That is, you try something, and if it doesn’t work you back up and try something else.  Simple enough.

It reminded me that when I was first learning Haskell, I wrote an n-queens solution using the Writer monad.  This monad just augments the pure functional environment with a new instruction called “tell”.  For those new to Haskell but with some knowledge of Python, consider it equivalent to Python’s “yield”.  Here’s the code:

import Control.Monad
import Control.Monad.Writer
import Data.List

diagonal (x1,y1) (x2,y2) = x1 + y1 == x2 + y2
                        || x1 - y1 == x2 - y2

nqueens n = execWriter $ f [1..n] 1 []
    where f [] _ ps = tell [ps]
          f cs r ps = forM_ cs $ \c ->
                          unless (any (diagonal (r,c)) ps) $
                              f (delete c cs) (r + 1) ((r,c):ps)

And that’s it.  The diagonal function determines if two positions (as order pairs of row and column) are diagonal from each other.  The nqueens function then uses execWriter to run something in the Writer monad and extract the list of answers that were “told” during its execution.  Then I call the workhorse function, which for lack of a better name is just called f.  This function assigns one queen to each row, from the top down.  It is recursive, so it tracks state in its parameters: the first is a list of free columns, the second is the row number, and the third is the list of positions where queens have been placed so far.  If there are no more free columns, then we must have placed all the queens, so we tell the solution.  If there are free columns, we loop through them and try putting a queen in each free column at the current row.

Formally, this returns a list of all solutions to the problem. However, it’s a lazy list; so if you only use the first one, the remainder of the list will never be calculated. So if you only want one solution, just do head (nqueens 8), and you’ll get the first solution.

Okay, nothing phenomenal here.  Just a quick example of some Haskell code.

Next Page »

Blog at WordPress.com.