Bio John Hughes is co-founder and CEO of Quviq AB, and the creator of QuickCheck. He was also involved in the design of Haskell being co-chair of the committee defining the language. He currently divides his time between his academic involvement as Chair of Chalmers University, Gothenburg, and QuviQ, the company promoting QuickCheck.
The Erlang Factory is an event that focuses on Erlang - the computer language that was designed to support distributed, fault-tolerant, soft-realtime applications with requirements for high availability and high concurrency. The main part of the Factory is the conference - a two-day collection of focused subject tracks with an enormous opportunity to meet the best minds in Erlang and network with experts in all its uses and applications.
I'm at heart an academic, I've been a professor for many years and I got interested in functional programming way back in the mid '70s. I've been working with it throughout my career, both with the design of Haskell and more recently, when the functional programming has become to make a move into industry, then I've been working with Erlang. So, I'm very much a fanatic of technology - I love it and very much enjoying seeing that it's finally bearing fruits. In industry, what I've been doing most recently is working with my testing tool, QuickCheck and spending a lot of time with my company that is marketing that.
We had a customer! Some of the Erlang users at Ericsson, especially Ulf Wiger were interested in using a version of QuickCheck, so I made a version in Erlang. At that time, certainly there weren't very many or perhaps hardly any Haskell users in the commercial world. So, if we wanted customers, then Erlang was a much better choice.
Yes, absolutely. I have Macros in Erlang that simulate it and I use them all the time.
4. And types?
Yes, of course. What I miss, when I think of type error, it's not immediately discovered and that's very useful, no doubt about that and I do spend some time looking for errors that the Haskell type checker would tell me about immediately. But what that means, is that I have to find my type errors by thorough testing. Oh, wait a minute, I'm working with a testing tool! I actually find that the type errors are found very quickly by QuickCheck tests, so I need to write QuickCheck properties for testing, anyway, so that it's not as big a problem as I might have expected not to have the type checker.
There are advantages than not having type checker, namely generic programming. If you do generic programming in Haskell, you can write a paper about it. If you do generic programming in Erlang, it's 4 lines - one for lists, one for tuples, one for basic values. Maybe they are only 3 lines! But it's very easy to do generic programming and I do that a lot in the Erlang version of QuickCheck. I've been able to make what the user has to write, to write QuickCheck specifications simpler and more elegant, thanks to the lack of a type system in Erlang. Erlang is very good for meta programming. It's not something that is a lot harder to do in Haskell.
This is some recent work we've been doing as part of the Protest project, which is a project that the EU Framework Program is financing and what we are doing is running current Erlang programs under control of our own scheduler. We define a scheduler as an Erlang process and we instrument the code under test, so that all of the other processes talk to our scheduler and they say "Isn’t it my turn yet?" Then, the scheduler says "Now it's your turn".
That lets us randomize the execution and makes it much more likely that we'll provoke race conditions. That's a fairly standard approach, actually. What is more novel about what we are doing is that we are generating the parallel test cases using QuickCheck. We found that we are able to shrink parallel test cases and produce the same kind of minimal examples that make sequential bugs easy to find. We can produce some of those that provoke race conditions. That's very interesting!
Yes. When you do higher order programming, you have to know what the types of your functions are. I do higher order programming all the time in Erlang and I know what the types of my functions are. They are a very valuable intellectual tool for understanding the complexity of higher order programs, whether or not you have a type checker that checks them. In Erlang I don't have a type checker that checks them, but that doesn't bother me so much.
8. Both Haskell and Erlang inspire the industry or mainstream in some way or another. Can you tell a bit about what are your favorite features from both languages that are getting mainstream in some way?
In Erlang's case it must be the concurrency and the very nice error handling and features for fault tolerance. In the case of Haskell, I guess it is perhaps Haskell’s ability to capture domain specific languages very elegantly, this having a lot of impact. There are several features in the language that make Haskell so good for that. One is the type system which is very flexible, another is support for higher order programming, which is really essential for defining many domain specific languages, but also lazy evaluation. Lazy evaluation is quite critical for defining the interface of a domain specific language.
In Erlang I have to use macros to get the same effect, because you want to be able to define constructions like conditionals that don't evaluate over their branches and lazy evaluation makes that easy to do. Some of my favorite Haskell applications are things like the financial combinators that Lennart Augustsson is working with, where you write Haskell code or what looks like a domain specific language, but is actually Haskell code that then generates Excel interfaces to the computing engines that perform these heavy financial computations - I think that kind of thing is really cool.
9. With Haskell you've been always thinking it's side effect free, right? Writing a function is side effect free. In Erlang just the fact of passing a message is a side effect. Don't you find it a bit of a problem or a difficulty when programming with Erlang?
Most of my Erlang programming is side effect free. I think I probably write very unusual Erlang programs that look a lot like Haskell ones. Now and then, I do write side effecting code. For example, when I use the random number generation libraries that comes with Erlang, it has a side effecting interface. It's very tempting when you are building something on top of the library with a stateful interface to build code on top of that that also has a stateful interface.
That's what I did the first time I tried to use it. That has caused me so much trouble. I think every single bug that I spent hours trying to track down has been caused by a side effect. In a way, I've been programming Haskell for so many years, that I'd forgotten just how devastating side effects are and just how difficult they make debugging. I've learnt that lesson again and nowadays, if I want to use a stateful library, I usually build a side effect free interface on top of it, so that I can then use it safely in the rest of my code.
10. Scala is a programming language that got inspired from different other programming languages including Haskell and Erlang, because it has actor model as a library and it has a pretty powerful type system. What do you think of this mixing of features? The same thing with F# which is trying to mix several paradigms, several things like dynamic and static typing in the same language for example. What do you think of this mixing?
I think it's great. My view of functional programming is always been that it gives us new useful tools. That's what I care about, rather than that it stops us doing bad things. You can always choose not to do bad things. I think, if integrating good ideas from several different languages makes an appealing combination, that's all to the good. I'm not a very purist about forbidding side effects absolutely, I simply choose not to use them.
Yes, I guess so.
There have been many clones, more or less complete. It's a nice idea.
When you write QuickCheck tests, what you write is a property and the properties of the form for all test cases in some set, some general property should be true. The difference from unit testing is that you specify a property of a whole set of test cases and then, when QuickCheck runs a test, what it does is it generates an element of that set. Your test cases are generated rather than being prescribed by the programmer. The property then has to determine whether an arbitrary test in this set has passed or not and that forces you to think more generally about the behavior or your code.
It's not enough to think "If I put in an A, I should get out a B". You have to think of a general property that will always be true. What you are writing is essentially a part of the form specification that can be more or less complete and the tool then generates as many tests as you like and checks the property of all of those cases. When a test fails, then the generated test case is often not very easy to understand. The reason for that is that we are using random generation. Random generation of anything produces a lot of noise. Somewhere in that test case, which can often be very large, there is some feature that causes the test to fail and we think of that as the signal.
The other thing that QuickCheck does is once we find a failing test that we know contains some feature that provokes a bug, we start systematically simplifying it and usually that works very well and we boil the test case down until we get a minimal example normally that provokes a failure. That automates a very familiar part of debugging where you start off with some complex case that has failed and often you would manually start trying to remove parts of it and simplify it and boil it down to a simple case that you can then understand and diagnose. We automate that process and I think that's what people like most about the tool.
14. For some time, Java was the language of the mainstream. Now we are hearing about lot of other languages, like Erlang, Haskell, F#. Do you think that there will be a next big language or we will be using a lot of languages for doing what we want to do?
Do you mean if there is going to be a winner? I suppose there will be maybe a small number of winners. If you look at Haskell, for example, there are certain kinds of programming that Haskell is truly excellent for and other kinds of programming, where it's entirely unsuitable. I don't think that Haskell will entirely replace C, for example. But, I suppose, in the long term, it's likely that perhaps one language of each kind will attract adherents, end up with better libraries, and in the end become the natural language of choice if you want to do that kind of programming. I don't know which languages that will be. Erlang seems to be doing very well at the moment for its particular niche.
Yes, but I'm pretty focused at the moment, I'm only part time at the university, part time at the company and we have this EU research project that is closely related to the Erlang work I'm doing at the company, so for natural reasons, just at the moment, that's where virtually all my time is being spent.
16. More than side effect free, are there other concepts from functional programming that you are applying in Erlang, like maybe monads or other abstractions that we see a lot in Haskell and other functional programming languages?
What I'm doing in Erlang is providing a domain specific language for testing and just like the domain specific languages that are provided in Haskell, higher order programming is a very important part of that, lazy evaluation is an important part because we are searching a space for minimal test cases and search processes are very nicely expressed in lazy evaluation and actually using a monad as well. I'm probably one of the few Erlang programmers who is using a monad. I think that many people, when they think about monads, they think that they are a way of doing IO without losing referential transparency.
Then, it's natural to think "Well, you can already do IO in Erlang, and without any need for monads, so why use one?" In fact, monads are useful both for capturing IO and as a program structuring concept. That I think is perhaps the more important use of monads and that's what I'm doing inside the Erlang code I'm writing. QuickCheck is based on a monad and it's not the same kind of monad that you do IO with. If you were, I wouldn't need it, but it enables me to structure the code of QuickCheck very nicely.
There is nothing corresponding to type classes.
I'm looking at a specific kind of application and in that application, then I don't think the lack of type class is really a big deal. One of the nice things about the Haskell version of QuickCheck is that we use type classes in order to generate test data of the right type and the programmer doesn't have to say anything, whereas, in the Erlang version, then you have to say "Generate me an integer" or "Generate me a list of integers" or "Generate me a protocol message" or whatever. You have to specify the generators, instead of getting them "for free".
At first sight, that looks like a disadvantage, but in reality, when you move beyond very simple properties, then you almost always need to specify generators. Generation is more complex than just saying "Give me an int". Maybe you want to generate a list and then generate one of the elements from the list for example, so you have dependencies between the things that you are generating. As soon as you move beyond very simple properties, you have to write the generators in Haskell also. Then, the fact that you have to write them in the Erlang version it's not really a disadvantage. You have to do the same thing basically.
I think functional programming is a very interesting concept for the future and for the present indeed. One of the things I do wonder about though, is when I got interested in the field, the mainstream was probably Fortran and COBOL and even C was fairly new at that time. The functional programming pioneers spoke of an order of magnitude improvement in productivity and I think functional programming has delivered that.
If you compare Haskell programs to C code or even C++ often, they are about an order of magnitude smaller and simpler. The same is for Erlang, those results are being validated in the industry. Where is the next order of magnitude coming from? I wish I had an answer to that question because it's hard to see almost. When you look at a beautiful Haskell program, how could this be 10 times shorter? But I think we need to be asking ourselves that kind of question. If I had a good idea there, I would spend the rest of my career working on it.
After "Some of the Erlang users, especially ...", I think he is saying "Ulf Wiger"
"When I think of type error, is not" -> "When I make a type error, it's not"
"attract adherence" -> "attract adherents"