Some say dealing with standard IO in Haskell doesn’t feel as ‘functional’ as some would expect. What’s your opinion?
Well it’s not functional – IO is a side effect as we discussed. IO ensures the launching of the missiles: do it now and do it in this order. IO means that it needs to be done in a particular order, so you say do this and then do that and you are mutating the state of the world. It clearly is a side effect to launch missiles so there’s no two ways about it.
If you have a purely functional program, then in principle, all it can do is take a value and deliver a value as its result. When Haskell was first born, all it would do is consume a character string and produce a character string. Then we thought, ‘oh, that’s not very cool, how can we launch missiles with that?’ Then we thought, ‘ah, maybe instead of a string, we could produce a list of commands that tell the outside world to launch the missiles and write to the disk.’ So that could be the result value. We’d still produced a value – that was the list of commands, but somebody else was doing the side effects as it were, so we were still holy and pure!
Then the next challenge was to producing value that said read a file and to get the contents of the file into the program. But we wrote a way of doing that, but it always felt a bit unsatisfactory to me, and that pushed us to come up with the idea of monads. Monads provided the way we embody IO into Haskell; it’s a very general idea that allows you to have a functional program that still includes side effects. I’ve been saying that purely functional programming means no effects, but programming with monads allows you to mix bits of program that do effect and bits that are pure without getting to two mixed up. So it allows you to not be one or the other.
But then, to answer your question, IO using monads still doesn’t look like purely functional programming, and it shouldn’t because it isn’t. It’s Monadic programming, which is kept nicely separate and integrates beautifully with the functional part. So I suppose it’s correct to say that it doesn’t feel functional because it isn’t, and shouldn’t be.
What Haskell has given to the world, besides a laboratory to explore ideas in, is this monadic idea. We were stuck not being able to do IO well for quite a while. F# essentially has monads, even though it’s an impure language, and so could do side effects. Nevertheless Don has imported into F# something he calls workflows, which are just a flimsy friendly name for monads. This is because even though F# is impure, monads are an idea that’s useful in their own right. Necessity was the mother of invention.
So monads would be Haskell’s lasting legacy in your eyes?
Yes, monads are a big deal. The idea that you can make something really practically useful for large scale applications out of a simple consistent idea is purely functional programming. I think that is a big thing that Haskell’s done – sticking to our guns on that is the thing we’re happiest about really.
One of the joys of being a researcher rather than somebody who’s got to sell a product is that you can stick to your guns, and Microsoft have allowed me to do that.