After nearly one and a half years away from it, I have finally been on the conference stage again. Devoxx Poland 2021 and the trip to Kraków has been an excellent experience. The city is remarkably rich in culture and history, so you will need more than just a couple of days to explore the city. In this blog post, I will tell you what inspired me to talk about Java and Haskell. But, first, here are the slides to the presentation and here is the recording.
My talk about similarities and differences between Java and Haskell may at first seem odd. Why would I even compare an object-oriented language and a purely functional language? I understand your reaction. First, comparing two programming languages, especially these two, isn’t something recommended doing when learning. Second, to learn a new language idiomatically, you must reset your mind from existing knowledge about other languages. Why did I make this talk then? The short answer is that Java is changing, and it’s changing fast. The new release cadence provides updates more quickly than ever, and the updates are predictable and reliable. Java and the JVM lay the foundations for other JVM languages. Developers keeping their knowledge up to date about the changes in Java is, therefore, more important than ever.
In my talk, I explain the direction Java is taking towards algebraic data types and exhaustive deconstructive pattern matching by showing examples in a purely functional language that already has these concepts. Haskell’s ultra expressiveness makes explaining and understanding these concepts easier and faster. I chose Haskell also because I wanted to avoid escape routes in object-oriented languages while learning functional programming. However, for the longer answer, a background into my journey with functional programming is necessary.
I started looking into functional programming when I first read Programming in Scala, written by Martin Odersky around 2012. The book made a significant impact on me since the world at this point was still at Java 7. Later, early access builds of JDK8 with JSR335 became publicly available, and most editors were steadily implementing support for lambdas. My first attempt to learn Scala was implementing a chess engine, so I started porting a chess program (see repo) from Mark Watson’s Practical AI Programming with Java. Mark’s code used the break
keyword to terminate loops in several places, and as a consequence, I recreated it in Scala. I soon realized I faced one of the fundamental principles of functional programming: avoiding side-effects (or handling them safely while preserving referential transparency with pure functions). Scala does not have break
for obvious reasons, but hey, it was possible, and I wanted to succeed in porting the code and getting it running (which I managed in the end). And this is one of the reasons I chose to learn a purely functional language when I started looking at functional programming again three years ago.
Between 2012 and 2014 here in Norway, head hunters must have gotten the impression that Java wasn’t going to get updated any time soon. Many conferences, JUGs, and communities were speaking about Scala (including myself). At the same time, I was getting an increasing amount of phone calls from head hunters asking if I needed a new job telling me Java is dead. When Java 8 did get released in March 2014, it changed the industry and communities. The upgrade to the Java language was so immense that even when Java 11 LTS was released, many still weren’t ready to upgrade. Some said it was because of issues with essential libraries, some said licensing, and some said legacy libraries blocked them. Today, this is no longer accurate, as many developers I talk to are telling me they have reached version 15 or 16.
Learning Scala gave me a better understanding of how Java 8 dealt with functional-style programming. For example, map-reduce-like transformations are built around streams
with intermediate (lazy functions) and terminal operations (finalizers), whereas they are part of the language itself in Scala. So you don’t have the overhead of creating streams, and the code is more expressive. On the other hand, I knew I wasn’t doing functional programming in Java, which does not support immutability, laziness, and deconstructive pattern matching (something Scala had for years, see case classes and sealed traits). Yet again, with switch-expressions added in Java and JEP-405 being on its way, this is about to change. Nevertheless, learning and working with Haskell and Scala gives you additional knowledge to make you a better Java programmer.
As the technological landscape was changing, other vital areas of the IT industry were changing too. In the architecture community, we saw how organizations were transitioning away from large-scale projects and instead adopting long-term product development in product teams. Substantial research and books such as Accelerate, Edge, and Team Topologies have profoundly impacted major organizations in Norway. At the Norwegian Labour and Welfare Administration (my employer), one of the largest governmental branches in Norway, we saw how the digital transformation dramatically increased agile product delivery, increased innovation, and increased ownership of all phases of our products. For increased ownership, teams select their tech stack and programming languages themselves. The latter allowed our developers to test different languages, and one that quickly became popular is Kotlin. Some of the reasons are that Kotlin is more expressive, less verbose, and allows a more functional coding style. As a result, we have seen a significant increase in delivery and quality when developers express themselves more freely and without Java’s verbosity. It is my strong belief, however, that things are about to change.
Java’s increased release speed will get Java closer to having better support for functional-style coding. Essential additions include sealed classes and interfaces, records, more robust type inference, switch expressions, and exhaustive deconstructive pattern matching (see JEP-405: Record & Array Patterns), including future support of with
/where
like concepts. In addition, the JVM will natively support syntactic sugar we know from other languages instead of being generated (thus allowing better optimizations). Haskell’s ultra expressiveness makes it easier to learn and explain functional programming. Haskell doesn’t allow me to take shortcuts or escape routes that are possible in hybrid languages. That is why Haskell has been my go-to language and why I made the talk.