Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Created October 27, 2017 21:17
Show Gist options
  • Save djspiewak/3d469a065eafeb9b2ddfcbd9d0c9b5a8 to your computer and use it in GitHub Desktop.
Save djspiewak/3d469a065eafeb9b2ddfcbd9d0c9b5a8 to your computer and use it in GitHub Desktop.

Very briefly...

In reply to some of the points from here. I understand the body of the post was more nuanced, though most of my arguments extend to the long form. Take this as an archetype of a full response.

Quick prefix though... I'm going to mention Haskell a few times. This isn't because I believe Haskell is a perfect language by any stretch of the imagination (if nothing else, its ecosystem is a hot mess). It's just a convenient noun that represents the category of language I'm thinking about.

solving a real-world problem => must use non-elegant models

I really hate this argument, because it starts out by implying that one party (presumably the untyped language users) are doing "real" work, while the other party (presumably the static typers) are not. Last time I checked, the code I write interacts with the real world. That is literally the whole point.

But to the second part, the argument starts by casually positing that some people do "real" work and others don't, and concludes by asserting that non-elegant models are fundamental. While I agree that often-times one has to represent ugliness with ugliness, I don't think that actually says anything about type systems. I write ugly representations in statically typed languages all the time, and I've written very elegant representations in untyped languages. And vice versa. This is literally the corollary of "you can write terrible code in any language." Types don't take away your ability to represent real-world complexity. They don't even hinder that ability. If they did, we wouldn't use them.

running all the time => must deal with state and time

I hear this argument a lot. I think it's interesting because it implies a shared belief that statically typed languages (or at the very least, pure statically typed languages like Haskell) have a hard time dealing with state and time as an explicit thing. That really couldn't be any further from the truth. State is explicit by definition in a pure language. Time (or equivalently, transition) is explicit by definition, and this explicitness allows us to build powerful abstractions and tooling with the confidence that it is accurate and safe.

Clojure is an ironic exemplar here because much of the language (and its core frameworks) revolve around being explicit with state and transitions on state. It puts forth the argument (which is a good one!) that this is a highly desirable property... and then many of its users proceed to say that static typing is a hindrance in this area, despite the fact that some of the most powerful and reliable abstractions around dealing with state and time exist in statically typed languages.

Now to be clear, I don't want to vilify anyone; many of the people making this argument are very well-intentioned and truly believe what they are saying. I can only assume that they simply aren't aware of how many of these things work in languages like Haskell. There's no shame in that, but it's important to understand that the argument stems from ignorance, not insight.

interacting with the world => must have effects and be affected

This is actually the same argument as the above, just in a different guise. It implies almost casually that statically typed languages are bad at managing effects and being affected. Nothing could be further from the truth. Pure static typing allows me to express what it means to be an effect, and build tooling and abstraction around that. I can control my effects with extreme precision and confidence, checked by the compiler, which is exactly what I want!

And really, what everyone wants who deals with effects. Effects are dangerous and scary things. You don't want them to happen at random times, or repeatedly, or (sometimes) in your tests. You want to make sure they don't step on each other, and are scheduled optimally. All of these things require very tight control. Not inconvenient control, but very tight control. Purity gives you control, and static typing allows that control to be automatically verified every time you compile your code. I fail to see how that is a bad thing, or in any way undesirable in a real system.

everything is changing => must change in ways you can't predict

Yep. See also "Real World".

It's not difficult to deal with dynamic data, schemata, etc in a static language. It really isn't. All that static typing changes is that it forces you to be explicit about the fact that you're working with dynamic things. It allows you to establish boundaries, beyond which all the variation has been factored out. For example, if you imagine a protocol definition, which must change over time in a non-atomic fashion (i.e. still accepting, correctly processing and responding-in old versions of the protocol). In a statically typed system, you're going to build an abstraction which factors out the differences between different versions of the protocol, while the rest of your program can rely on the hard, machine-checked fact that you have one internal abstraction. And if that isn't sufficient (such as deeper semantic protocol changes), then static typing forces you to be explicit about the branching at various points in your system. Static typing allows machine-checked compartmentalization and explicit modeling of the problem space. It gives you safety at a very high semantic level. Far higher than simply "is this String accidentally an Int?"


I have plenty of examples of all of this. In real applications. That interact with real data. With real state. Over time. That constantly run. And change. All of it. And I can't imagine writing (much less testing or maintaining!) any of those examples without the safety and security that static typing provides, or the magnitude of abstraction that is enabled by machine checking.

This isn't really about static vs dynamic typing though. That's a relatively trite and well-trod argument that honestly just doesn't go anywhere interesting. This is about ways to write reasonable software. Software that we can test and maintain and to some degree understand. Software that can solve hard problems and messy problems and real problems (which are really all of the above). This is about all that and more. And it's about trying to get everyone on the same page about the options that are out there, because so many of these arguments (often on both sides) are rooted in ignorance of what the "other side" actually does, actually struggles with, and is actually capable of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment