Caveat: I am not a computer programmer by profession. I am a hobbyist who loves to dig around programming in my free time. Many of the words used in this essay may not necessarily be formally correct and I invite knowledgeable people to share their feedback.
Since I've been fascinated by Haskell for a while now, I thought this would be a good time to post my general thoughts on Functional programming with respect to Haskell in particular.
To be honest, like most others coming from an imperative (procedural) programming background, functional programming was daunting. There were so many new concepts and some mathematical jargon used in Haskell tutorials that initially put me off, but then I kept digging deeper. I don't claim to understand most of the advanced concepts yet, but I have got a feel for functional programming that I think could act as a basis for future learning.
Haskell is a wonderfully abstract, pure functional programming language with features such as non-strict evaluation and a strong powerful static typing system and a rich set of useful libraries. To understand functional programming, here are some ideas I feel will help newbies (like me). There are a lot of tutorials that introduce FP in terms of purity, referential transparency etc. I assume that you have read those. Here I am going to try to condense my thoughts on how best FP can be understood without getting bogged down in theory.
Without further ado then...
It's all about data and data transformations
I like to visualize functional programming (FP) as primarily about data and how data is transformed. Think of (pure) functional programming as a series of data transformations that takes inputs and produces output with a guarantee that a certain input will always produce the same output. Data is passed in and out of functions and they assume different shapes (types), finally yielding the desired output.
It's amazing how quickly the necessity for imperative style disappears when seen along those terms. No longer do you require mutable or global variables since functions do the job of data mutation transparently. No longer do you require iterative looping, since functions can naturally be called recursively. Every other basic concept of FP fell into place when I grasped this.
No wonder then, that FP is a good fit for straightforward data-transformation problem domains. It is easy to learn functional programming by first approaching the obvious and direct applications of FP such as text/binary parsing and mathematical/numerical problems.
Other problem domains build on top of these bases, but introduce other conceptual distractions in terms of I/O, state management and user interaction.
Abstraction is not what it seems
Many from a programming background consciously or unconsciously assume that "abstraction" equals "implementation hiding". This is the common (but flawed) OOP usage. In functional programming, abstraction is seen as a way to derive a general pattern or solution by observing specific but distinct patterns or instances. The higher the level of "generalization" the tougher it is to mentally map the idea.
I think this is one reason why Haskell is tough to grasp. Sure, a lot of implementation hiding takes place in functional programming languages, but it's not just implementation hiding. A lot of concepts are abstract and tough to mentally grasp because abstractions describe generic patterns.
Books are good but write your own code
I've found that writing my own code is the best way to understand Haskell. Books and tutorials are great, but following them can be tough, because the difficulty of grasping abstract concepts can grow exponentially unless an earlier less abstract concept is understood thoroughly. Understanding can be greatly aided by application. And that is one reason why I think writing code without following along any tutorial/book is a good way to learn the language.
Not being bogged down by the theoritical portions of FP or unfamiliar problem domains is another reason to write code without any aid. The problem with tutorials or books is that they tend to introduce different problem domains to illustrate different concepts/techniques and sometimes the reader is not familiar enough with the problem domain in the first place. This severely hinders understanding of the concept of technique that is sought to be explained or illustrated.
The result of writing one's own code may be idiomatically incorrect, conceptually flawed, or straight out wrong, but unless one writes code, one cannot figure that out. The other thing I realized about writing one's own code is that one develops a kind of intuition for how things "work" in functional programming.
Pick a style and stick with it until concepts sink in
Some of the Haskell code I've seen on (even beginner) tutorials are extremely terse, yet quite tough to mentally scan and understand partly due to the strange syntax and partly due to the use of non-obvious higher order functions.
I find that being a bit more verbose initially is a good aid to conceptual understanding.
I do understand that the style of programming does make a difference algorithmically, and sometimes in terms of efficiency or performance. However, once the concept is digested, it becomes much easier to scan terse code. What is important initially is to know the solution, and only then to figure out how to improve it. Being spoon fed with a perfect solution right at the start can be tough to conceptually digest.
It all takes time
All said and done, FP, especially as viewed through the lens of Haskell, is tough. It takes time and effort to learn even the basics, but can be fun too, because you are re-introduced to the basics and find newer avenues to explore classic problems. It's like rediscovering computer programming all over again.
I think #haskell on Freenode is a great way to connect with the knowledgeable members of the Haskell community. It can be daunting to read the some of the advanced topics discussed there, but newbies are always welcome and no question is too basic to answer.
In this series
- Musings on Functional Programming and Haskell
- Tic Tac Toe (a.k.a Noughts and Crosses) in Haskell
- Five tips about Functional Programming for a Haskell newbie from a Haskell newbie
- My Haskell article was linked at reddit
- Why learning Functional Programming and Haskell in particular can be hard
- Something about Haskell I wanted to share
- So on to learning Haskell