Programming

Abuse of Sum Types In OO Languages

Sum types are useful, but they are also an attractive nuisance in object oriented languages. There's a certain type of programmer who gets a taste of functional programming and has a good time, but misinterprets that good time to mean that sum types are always better, because they are FP, and FP is Better.

But sum types are not generally better, they are specifically better. Using sum types, or even forcing sum types into languages that don't really have them like C, is a valid solution for certain problems, but in most cases they are not the best choice.

To understand when sum types are best, you must understand something called...

I've said a few times on Hacker News over the years that I don't think you can have a single shell language that covers the interactive and programmatic use cases, but I have not yet talked through it enough to myself to crystallize the point. I think I have it now. Interactive shell usage is optimized for the fact that a human will be examining the state of the world after every shell command.

Functors and Monads For People Who Have Read Too Many "Tutorials"

Title is literally true. This may not be the best place to learn about these concepts for the first time, because I'm going to focus on knocking down the misconceptions about them.

Then again, it may not be the worst place, for the same reason.

I had promised myself I would not add to the pile of functor or monad "tutorials", but I've been worn down. I gave up when I saw a reddit comment complaining about how Functor was "too hard to understand", which made me sad, because the correct response to the Functor interface is, "That's it?". And while Monad is legitimately a bit more interesting and complex, the correct response to that is not that different.

I am aware of the notorious effect that people "get" monads and then post their own idiosyncratic takes on them. In my defense, this isn't something I write just after my "ah ha!" moment, I've understood them in Haskell's context for many years now, and actually... this isn't even about that "ah ha!" moment at all. This is only about what they are. Even if you completely understand everything I write in this post, the real "ah ha!" where you realize just how useful the libraries built up around the monad interface are, the first time you search for a type on Hoogle where you're like this should exist and it turns out it does in fact exist already, that's still in your future. In fact I'm quite deliberately not trying to convey that feeling in the interests of getting at simply what the monad interface is. Which isn't, strictly speaking, a pre-requisite to that experience, but it does help.

Interfaces and Nil in Go, or, Don't Lie to Computers

It is commonly held up as a wart in Go that interfaces have "two different nils"; one is when the interface value is nil:

var something interface{}
fmt.Println(something == nil) // prints true

and one is when the interface contains a nil:

var i *int // initializes to nil
var something interface{} = i
fmt.Println(something == nil) // prints false

This is not a wart in Go. It is a result of a programmer misconception combining with a software engineering bug which results in an attribution error.

Why Go Getting Generics Will Not Change Idiomatic Go

After years of overly-acrimonious online discussion, Go is continuing down the chute towards getting generics. I'm already seeing the inevitable "functional" libraries (plural) coming out. I'm going to explain why none of these libraries are going to materially impact what the community considers good style.

They may see some use. I may even use some of them myself on small scales. Some iconoclasts will program with them extensively, and their code will work, in the sense that it will do what it was designed to do regardless of how the code reads. But they are not going to change what generally-good style is considered to be.

Edit: May 2021 - Update for the latest generics syntax.

Why Duck Typing Is Safe

For the last 20 years I've been programming almost exclusively in languages with either duck typing or structural typing. These are languages where you can have objects that either conform to an informal interface without that conformance being declared (dynamically-typed languages), or where conformance is simply a matter of matching the interface (Go). This is as opposed to languages where conformance must be explicitly declared somehow, either with a formal subclass relationship (the class-based portion of C++) or by explicitly declaring conformance to an interface (Java).

Not needing to formally declare conformance is powerful because you can take some pre-existing object, declare a new interface that it conforms to, and then use it with your interface. This reduces the endless paperwork around re-wrapping things to make existing objects conform to new interfaces.

I have seen a lot of programmers over the years express concerns; what if something accidentally conforms to an interface and causes some horrible bug? What if I have an interface for Shoot() for a video game and some object wanders in that Shoot()s a real gun by accident? Isn't it safer to formally declare conformance?

Avoiding Reflection (And Such) In Go

So, as previous posts show, I like Go well enough. But as a computer-language polyglot, "Go programmer" is not part of my identity, and I try for a balanced view. It is very human to go overboard in both praise and criticism, both easy to find online.

I open with this because this post will take a, ahh, let's say nuanced position on Go, in that it is going to agree a bit with both sides. Go's type system is weak and there are cases where you can only accomplish something via interface{}, reflection, copy/paste, or code generation... but in a rush to talk about what Go doesn't have, what it does have is too often neglected. When using a tool to solve problems what matters is whether there exists a good solution with that tool, not whether a direct port of a good solution from some other tool works. There certainly are real problems that lack good solutions in Go, but that set of problems is smaller than is sometimes supposed.

Some languages provide many power tools, and it is easy to use a bit of one and a bit of another without ever using any individual tool very deeply. Go provides you only a few tools, so you should use each fully.

If your Go code is a horrible copy/paste disaster, you must figure out whether it is because you are not using tools fully, or if you are missing tools. If you are missing tools, use another tool set. I do not consider that any sort of "concession", because I'm not too interested in whether you use Go; I'm interested in showing people how to fully use tools. All of these techniques will work in other languages as well, with varying degrees of convenience.

It's 2015. Why do we still write insecure software?

I've read a lot of programming blogs, and if you're reading this, you probably have too. So let me tell you up-front this is not your usual security rant that boils down to "just try harder!" Let's talk about smart, experienced programmers who are trying to write secure code, even if they are not security "experts" per se. This is an important set of people, because there is more security-related software in the world to write than can be written by security experts.

In a perfect world, setting that as the target audience would conclude this essay. As your browser's scrollbar shows in the full view, this essay continues on for quite a while. Alas, decades of experience and a trained reasonably high intelligence are not sufficient to write secure software in the current coding environment.

That's also the highest amount of qualifications that can be feasibly brought to bear at any reasonable scale, so in practice that's equivalent to saying it's impossible to write secure software in the current coding environment.

Let's talk about why it's so hard. My thesis is simple:

We write insecure software because our coding environment makes it easier to write insecure software than secure software.

But exploring what it fully means can lead some surprising places. Please join me on a journey as I try to show you why that is not trivially true, but in fact, profoundly true. We do not occasionally pick up insecure tools, like a broken encryption routine or misusing a web framework; we are fish swimming in an ocean of insecurity, oblivious to how steeped in it we are.