This article is a response to this blog post. The problem with this post is that it makes several mistakes around the behavior of sum types, which undrcut the argument the post is making. I want to explain why Bob Harper’s original (and admittedly some-what flaime-baity) post is correct.

But first, I need to actually state the argument Bob Harper was making. He was said that every dynamic language could be incoded as a sum type in a static language. As example of this, let me demonstrate exactly how to do this, by encoding lisp into a sum type in haskell:

This says a Lisp value is either an Int (labelled with the tag LInt), a String (LString), a Symbol (LSymbol), or a list of Lisp values. You can, if you feel like, extend this with more data types- add floats, and doubles, and chars, and vectors, and maps, and sets, etc. I can then happily write functions that take and return my Lisp values.

At this point, the OP makes a critical error right about here- she assumes that the values 3 and LInt 3 are the same. They aren’t. No, you can’t add an integer and a string in Haskell- but you can write an add function (of type Lisp -> Lisp -> Lisp) which can add an LInt 3 to an LString "foo".

This is interesting because it demonstrates another point the OP missed. So let’s consider the add function, to add two lisp function together. As there are two arguments, and each argument can be one of four different types (variants), you might think I need to write 16 different case statements down. You’d be wrong. The code looks like:

The _ is a discard matcher- it matches anything. And since matching precedes in order, and the first pattern to fit is the one that is evaluated, if both arguments are ints, the first expression is evaluated, and we get an int. If any of the other 15 different situations occurs, then the second expression is evaluate, and we throw an error at run time. Just like Lisp. In this way, the _ acts as a sort of escape hatch from having to deal with all the different cases, which all get handled the same way anyways. Indeed, the whole Lisp type itself acts as a sort of escape hatch.

From one angle, all Bob Harper has done here is restate Greenspun’s tenth law. But here’s the difference, and the point Harper was making: we can choose not to use the Lisp type. By taking a value of type Lisp, we are expressly stating that this function takes any value that can be encoded as an s-expression. If that’s what we mean, all right. But we have the choice of using a more restrictive type, we express something of the assumptions the function is making.

This is what Bob Harper meant by more expressive. Everything we can express in language X was can also expression in language Y- but there are things we can express in language Y that we can not in language X. For example, that a given function doesn’t handle every possible case.

OK, I’m wigging out again. The debate has come up *again* as to whether or not programmers need to know math. The answer, in my mind, is an unarguable “yes”. If you don’t, then many things will be extremely hard, and some things impossible, which people who do know the math will find quite easy. But rather than take the high road, and make vague and unconvincing general arguments, I thought I’d dive down into the details and list the higher level mathematics I’ve found useful in my programming career. Note that the high school level mathematics- algebra, geometry, trigonometry, I’m going to ignore. This is the higher level stuff- stuff mathematicians think is mathematics. This is a personal list, and off the top of my head, so it is no doubt incomplete.

Let’s start with graph theory. If there is on branch of mathematics a programmer can’t live without, this would be it. It’s about things (nodes) that have relationships (edges) with other things. Like cities connected by roads. Or- in the more programaticaly useful, objects with pointers to each other. Pretty much all data structures are graphs. Run the standard graph theory algorithms to find out which objects can be reached from some set of root objects, and you have a garbage collector. Or how about this: functions that call other functions- the functions are the nodes, edges represent that one function calls another. Reachable algorithms tell you what functions can be dispensed with. Do a clique finding algorithm, and this determines which sets of functions for recursive loops. And so on. ‘Cmon, people- damned near everything we do as programmers is dealing with things that have relationships to other things.

Next up is linear algebra. Want to do 3D programming? Welcome to linear algebra. Lots and lots of linear algebra. Learning quaternions and geometric algebra is probably a good idea too- but linear algebra is a requirement. But linear algebra is useful for way more than that. Lots of other forms of mathematics (for example, graph theory) tend to reduce to linear algebra. Machine learning also uses linear algebra heavily- if you want to write an algorithmic trading platform or a search engine, better brush up on your linear algebra. Add in a dash of calculus, and you’re solving systems of non-linear equations (via Newton-Kantorovich).

Numerical analysis is how to implement linear algebra is the real world (i.e. on computers). Also, it covers the care and feeding of floating point numbers. If I were king, programmers would be required to pass a class on numerical analysis before being allowed to use floats.

Abstract algebra and number theory are useful for cryptography, random number generation, hashing, error detection, and a couple of other things. For example, 2′s complement arithmetic makes perfect sense once you realize that it’s just arithmetic modulo 2n.

Statistics. How could I forget statistics? There is more to statistics than Bayes theorem (and Bayesian reasoning), but for that alone it is indispensable.

I’m not sure what branch of mathematics Fourier transform falls over, but it’s another one that shows up all over. Including weird places, like multiplying large numbers.

There are a lot of “little branches” of mathematics, which aren’t full disciplines themselves, but are still worth learning. Knowing the relational calculus makes SQL make a more sense, knowing the Pi Calculus makes Erlang make a lot more sense, knowing the Lambda Calculus makes Lisp and Haskell make a lot more sense, and so on. Being able to at least read and follow the mathematicians gives insights into the fundamentals of what is going on.

For the record, I don’t know category theory, and don’t feel any deep seated need to learn it either. I haven’t got my head around geometric algebra yet, and I want to take a swing at algebraic topology at some point (to take a deep approach to relativity and quantum mechanics). Speaking from experience, it’s certainly not necessary to learn Haskell or figure out monads.

But, at the end of the day, there’s this. Programming is about solving problems- that why anyone cares about it. What’s important isn’t the code produced, it’s the problems solved. And mathematics is about how to solve problems. How do these two things not go together like peas in a pod? Richard Feynman once compared knowing different mathematics to having extra tools in your tool chest. Not all mathematics is applicable to all problems, granted- but learning mathematics is like learning new APIs, or new languages. It allows us to solve problems we otherwise couldn’t.

First of all, we have to be clear that a statically typed Groovy is going to have to do away with a lot of functionality. After all, this is totally legitimate and well-defined Groovy code:
class Foo {}
new Foo().abjdslkfansdawkejras()

The specified behavior is that it throws a NoSuchMethodException. If this is to be respected, then no method call can ever be identified as erroneous in Grumpy-mode Groovy. My guess is that this is not what they are going for, and that code would be flagged as an error (or at least a very strong warning) in Grumpy mode. So, basically, we aren’t talking about statically typed Groovy. We are talking about a language that looks kinda like Groovy, but doesn’t have all the features, and is statically instead of dynamically typed.

Similarly, though, you’re looking at having to get rid of metaClass mangling, methodMissing/invokeMethod, and getProperty and setProperty. This means basically all builders are out, as are context-sensitive methods (e.g. GORM domain objects). You’re also going to have to get rid of any code that uses any of that functionality, which includes the Groovy SDK: things like List#forEach are metaclass stunts. This means you’re talking about a static mode for Groovy which is not only missing many of the key features of Groovy, but also is not even compatible with non-static mode Groovy code.

At this point, it’s probably fair to point out that a static mode for compiling a subset of Groovy already exists: it’s called Java. Once you get away from chiseling away the dynamic features, I think all you’re left with is post-Coin Java plus closures. If Groovy provided a nicer bridge to Groovy closures from Java, I’m really not sure what they have left to gain. And considering that the Groovy core development team is going to have to support Grumpy, whereas Oracle supports Java, this seems like a bad strategic move.

All in all, I’m just totally confused about what motivates this move. It can’t be functionality, because we’re actually losing functionality in the language. It shouldn’t be performance: Headius seems to have no problem optimizing JRuby like crazy without having to fall to a “static mode”, and GPP seems to be doing okay with plugging static code into Groovy. I suppose it could be error checking, but if that’s the case, then it seems like the Groovy core team is declaring the static vs. dynamic type war over, and static won. If that’s the case, they should shift over to Scala (or fund my Ashlar development), because they’re about to rediscover a lot of the pain of developing a statically typed language, but with the added difficulty of having to be congruent (for some limited meaning) to a dynamic language.

I’ve been working in .NET for a while now, but the time finally came when I no longer had to be working on a Microsoft workstation via VPN. This meant that I was free to start developing .NET on my Mac, and that meant starting with installing F#.

I presumed I was going to have to do some kind of hardcore magic dance to get this to work, so imagine my surprise when I fired up MacPorts for shits and giggles but actually discovered an fsharp port! It even seemed reasonably up-to-date! What a world!

So I began with the three steps beginning basically every serious endeavor on MacPorts: a selfupdate, an upgrade outdated, and a clean installed. I then dove in: install fsharp.

Unfortunately, the libgdiplus port (a dependency of fsharp) failed to build for me. Some googling around and I found a ticket saying that I failed to build its dependencies with +universal, so I should do that. According to the ticket, the problem was probably cairo, so I fired off upgrade --enforce-variants cairo +universal, and that got me a bit further, but no ultimately it failed again: libsasl (from cyrus-sasl) was apparently also of the wrong architecture. About this time I was having Gentoo flashbacks, so I fired off upgrade --enforce-variants installed +universal, because sometimes the only way to be sure is to take off and nuke the site from orbit. That completed just fine after an hour or so.

Another install fsharp later and I got past libgdiplus. The mono and fsharp ports installed like a breeze. (It was a very slow breeze — more like stagnant air being pushed around by a decrepit fan — but it worked all the same.)

So far, things look pretty good. I have to run the fsi as fsi --no-gui --readline for some reason, but that’s pretty minor.

A few years back, I started exploring programming language implementations. Generally, I wanted to understand the kind of decisions and trade-offs that programming language designers make: specifically, I was curious as to why Scala made some of the decisions that they did, and so I went down the road of trying to build a language that “fixed” what I perceived to be issues in Scala. That language was called Cornerstone.

After a while, I discovered that there are good reasons why Scala does things the way it does. In those “fixes”, what I was asking for was basically having my cake and eating it, too. Cornerstone was born of naiveté, and so while it was a wonderful educational opportunity, it was a stillborn language.

With lessons learned, I reconsidered my approach and started in on a new language, Ashlar. In my free time this summer, as a counter-balance to the pastoral/ministerial work I was doing, I cranked on Ashlar. It’s still just getting started, but a big hurdle has been crossed: the runtime is up and running, and the compiler infrastructure is in place. The functional test of printing “Hello, World” has gone from red to green. By request, I’ve added a bit of a description up on the Ashlar wiki, so go check it out.

In particular, there is an extensive conversation about the assumptions of Ashlar. Let me know what you think about that: I’m very curious.

The tools are developed to work around short comings in the language itself. If the language didn’t have those short comings, you wouldn’t need the tools, and they wouldn’t get developed. The best language would be just fine with just notepad and a compiler. So bragging about how great the tools are for your language is bragging about how your language sucks, and needs significant amounts of help to make development in it tolerable.

Just a quick note, I wanted to point this paper out to everyone here. Basically, the author demonstrates a denial of service attack using engineered hash collisions to force the programs into worst case behavior situations, just like I commented way back then.

And I’m not sure how much faith I’d put into a new hash algorithm being the savior here. The security of the system now relies on the cryptographic robustness of the hashing algorithm- remember, the attacker only has to find a sequence which demonstrates worst case, or near worst case, behavior in order to launch the denial of service attack. So if there is a cryptographic flaw in the algorithm which allows a malicious attacker to discover collisions much cheaper than brute force, then it becomes computationally feasible for the attacker to compute the worst case sequence, especially once they put their botnet on to it.

This is something that has been bothering me for a while. Never, with the possible exception of “Democrats are weak” (thank god we had a real conservative as president when we fought global fascism, and not some lilly livered spineless liberal Democrat), have I ever seen a baseless criticism be so eagerly adopted by those whose are criticized, as with the Unix-hating diatribe The Rise of Worse is Better. And baseless sour grapes it is.