Learning to process thoughts with Haskell
“Once upon a time, there was a mathematician named Alonzo Church at Princeton University. Church was Alan Turing’s PhD supervisor. Church devised a mathematical model of functions called lambda calculus. Yes, this is where modern-day lambdas come from!” - quoted from Brief History of Haskell
Alan Turing! Known to be the one of the pioneers of computer science field. Also known as one of the founders of functional programming. That was what I was exposed to in a Programming Paradigms course, widely known to be the most challenging course at Monash. In fact, that is indeed true - the toughest course at Monash. During the first few lessons of the course, I thought “functional programming” is like any other programming model - “an approach that is functional enough”, so that’s why it is called “functional programming”. But I was wrong weeks later, I didn’t realize that there was actually a close association between programming and the concept of a mathematical function - f(x) or g(x)!
My first exposure to FP was learned through the Haskell language. I will skip the history part of Haskell. What is Haskell? In short, a purely functional programming language. Zero mutability. A language that focuses on ensuring that every data is as clean, as pure and as original as possible. From the perspective of imperative languages like C++, Python or Java, it means no if-else, no for-loops and only functions are permitted. All operations must work within functions, under the concept of input and output. In imperative languages, you learn about getting things done by giving the computer a series of instructions to execute. On the contrary, in functional languages, you get things done by not telling the machine what to do, but you tell the computer what it is or what to do. In sum, imperative teaches you “how to think” but functional teaches you “what to think”.
That was the start of the shift in thought process. It was a fundamentally and a whole new paradigm exposed to me. I started to dig stuffs about this intimidating and grinding language. In PFP (purely functional programming), you express everything in the form of functions. You can’t set a variable to something and then change it after a while. That is because if you do, it will no longer be “pure” and causes some side effects. And the consequences of having these side effects will be it makes you harder to debug and trace your bugs. On the other hand, it actually have some good effects. Since zero side-effects is the focus here, that means a function being called multiple times will have the same effect, returning you the same result.
I learned that the term “referential transparency” - it allows you to easily prove the correctness of a function and join up complex functions togethers. In short, if f(x) is true, I can make f(x) to be the input of g(x) to form a new function called f(g(x)). This language made me to “rethink” about mutating the information of a program. I also learned the term “statically typed” - it means a variable can only be represented by a single type. Once you define a variable with a string, and when you try to add a string with a number, it will not compile. That means, you need to handle your variables with extreme care and a focus over the process of thinking.
Haskell was built up by some smart PhD geeks. It is no secret that it is certainly considered to be an academic language. It builds on top of lambda calculus, which you don’t usually find them in the industry - it is uncommon to be used. Why? The whole language is built on top of mathematical concepts, so few without deep knowledge in math will truely grasp the ideas. Concepts like functors, lambdas, monads, monoids creates no clue, because there is a “twist” in the connection with the human brain. But ideas like loops, if-else, class, variables - fits in naturally with our brain. Since there are few people actually using it, so the resources out there was comparatively small than imperative languages like C++. And it fact, that was what I experienced in the debugging Haskell programs. The same problem in Java took 1/10 time but Haskell took me 7/10 time.
Learning Haskell was sometimes pointless and unncessary in a practical sense, because it doesn’t yield much industry effects. It is undeniably true that it is intellectually satisfying, but the problems encountered are time-consuming. You will be better off spending time learning something else that have a practical usage for a few years. You can skip steps in other languages, but you have to take one step at a time for Haskell for you to transition your thinking approach from imperative way to functional way. It was a life-changing experience.