
Learn Me a Haskell
An OOP Developer’s First Impressions
“2016 is the year I dive into functional programming!”
I told myself in January — then I looked up and realized I only had two months left in the year. So with the below quote in mind I’m finally getting to it.
“The best time time to plant a tree was twenty years ago; the second best time was nineteen years ago; the twentieth-first best time is now.” 一位匿名的中国人
My academic interests lean heavily towards Artificial Intelligence, so a programming paradigm focused on patterns seems like a productive fit for expanding my skill-set.
That’s the hope, at least, and thus a desire to learn Haskell which seems to have a vibrant community. Sure, it may have a logo that reminds me of a grocery store chain more than its actual inspiration (the lambda character λ), but it looks, from the outside at least, very accessible.
In fact, a quick Google search reveals a mind-blowing online tutorial promising quick exposure to Haskell: TryHaskell.org
Let’s see how an OOP developer handles an initial exposure to functional programming with Haskell.
Note: In all seriousness, these are my first, amateur reactions to functional programming coming from a long background in procedural and OOP. Nothing I say is meant to deride the work of the Haskell community or the tutorial: I guarantee any confusions are genuine first learnings.
tldr; Everything goes up in flames in Part 5.
1. Kudos to Chris Done: This is a Slick Tutorial
First impression: this is a great intro.
The website does a good job of not getting in your way — from the get-go you know what to do and what you’re expecting to happen.

I do in fact have 5 minutes, so I’m going to give it a shot. Although I’m surprised the distraction of other sample commands is so prevalent instead of being spaced down a bit.
No matter. Let’s type in “help” and get started.

Alright, the first example is just adding two integers together. Reminds me of the Python interpreter.
No confusion here. Let’s just type in “5 + 7”

OK. I was in fact expecting 12
and the Tutorial let me know I typed it correctly. This was indeed what I wanted to see.
The only question I have is what the heck is:: Num a => a
?
Maybe they cover that in the next section? Reading along I’ll try something “completely different” and I’ll type my name in the style of a quoted string: "tim"

Ah, got it: I put in a string, I get a string.
It’s giving me back the value of the expression and some sort of shorthand for the type of the returning value, I think. :: [Char]
must have the semantic meaning of ‘array of chars/list of chars/string’?
Moving on, now I’m asked to make a list of numbers in a bracket-array style.

I’m done already with Lesson 1? Wow, that was quick.
Inventory: so far I know I can add two integers, make a string, and make a list of numbers.
Hmm, there’s that :: Num t => [t]
style structure again, which is different from the result of the addition I performed earlier :: Num a => a
— still unclear here, I’m not sure if my intuition is misleading me that the new expression means that the new result is a ‘list of Num’ and that the former result of the addition was a single Num.
The next lesson beckons me to type in “sort [42,13,22]”
2. Funk in Function — Yes You Put It There

No strange surprises so far with using the sort function, besides the fact that some of the decoration expected like parentheses are unnecessary. I’m still reading left to right and semantically parsing it as “sort the list of numbers containing 13, 22, and 42.”
Oh no, wait. What’s the :: (Num a, Ord a) => [a]
mean? Why are some of these a and some of these t? I’m obviously getting easily distracted here.
If I run sort "tim"
I’m going to expect it to treat it like a list of chars, and end up being ‘imt’ — just based on context.

Great! The characters are sorted and the resulting type was :: [Char]
and so far my nascent worldview of functional programming hasn’t been utterly shattered.
Oh, we’re talking about tuples now? OK. Let’s type in (28, “imt”)

We want to retrieve the age from the tuple (28,"imt")
and it looks like there’s a function called fst
to do so.

fst
turned out to be the function for getting the first item in a tuple, so rather than typing first
they’ve shortened it to fst
since apparently used so often — which makes sense if the first value in a tuple gets treated as a key in lookups, I imagine.
My initial reaction is that there must be a scd
function for second
but then would there be a thd
function for third
? Sounds a bit like a turtles all the way down problem…
We finished Lesson 2 though!
Inventory: I can now sort, create a tuple, and pluck out the first value in a tuple.
Confidence Level: I’m OK. Still not sure about the type(s) of the expressions being evaluated, but so far I’m alright with the syntax.
Next it’s asking me to create a variable.
3. Let’s Be Variable-ing

I’m reading this explanation very carefully because let x = 4 in x * x
is ambiguous to me. My procedural or OOP side wants x
to be assigned the value of 16
but is that what’s really happening?
Or is it that x
is assigned a value of 4
and the result of the x * x
is 16
which looks like an anonymous function body?
It definitely seems like the latter based on the description:
let var = expression in body
The next step looks promising for the second line of reasoning if the following is a correct interpretation:
- Create a tuple with Num 28 and String “imt” being items 1 and 2 (or is it zero-indexed? Or is that not even relevant in Haskell?)
- Assign the tuple to the variable
villain
- Using the expression/variable on the left, get the first item in the
villain
tuple using thefst
function - The result should be
28

28! The ball is rolling. Now let’s try another variable just to be… oh, we’re done with variables now, I was just about to ask questions about the in
keyword but we’re moving on to syntactic sugar.
“Syntactic sugar causes cancer of the semicolon.” - Alan Perlis
I’m going to go ahead and type 'a' : []
— no clue what this is for, even if I feel like I should since they’re already telling me about syntactic sugar. This feels like the exact opposite.

The result being "a"
. I see what you did there! "a"
is the syntactic sugar for 'a' : []
, right?
So :
is actually a function called cons
? I will remember this, and the following logic about 'a' : 'b' : [] == ['a','b']
makes sense. I’m assuming that 'a' : 'b' : [] == "ab"
as well?
For a moment I didn’t really get the prompt, then I realized it wanted me to run the equality and see for myself.

Bools exist in Haskell! Nice. Also, really love the positive feedback.
And sure enough there’s a demo for ['a','b','c'] == "abc"
as well.

Sweet indeed; that wasn’t much to absorb for Lesson 3.
Inventory: I can create a variable with let
, was exposed to the keyword in
, can grab the first item of a tuple with fst
, and understand some basic syntactic sugaring around lists, char strings, and the :
function.
Confidence Level: Still good with no major hiccups so far. Everything is starting to feel like a list.
Still not done though and there’s a new thing to try: map (+1) [1..5]
4. Functions of a What Now?

That did… pretty much what I would’ve hoped for. The [1..5]
looked like a list of integers from 1 to 5. I’m going to make another assumption that ..
means range.
The map
function looked like it would perform the +1 operation on each element in the list, and that logic seems to have borne out with the resulting list [2,3,4,5,6]
.
You haven’t lost me yet, Haskell!
Reading further, though, it seems (+1)
is considered to be a function? Also, tuples are back, so let’s explore the example of (1,"George")

I notice just now that I’ve been confused without realizing it — reading the words on the page now I’m answering the question “How are tuples and lists different?” to myself.
Lists are composed of elements of the same datatype, and can be made on the fly (composing, decomposing I assume?)
Tuples can have mixed types but are declared all at once.
Meanwhile, on to writing our own functions!
let square x = x * x in square 3
I’m really getting the idea here that everything after in
is another function using whatever came before (which makes sense, given it being called the body following the expression).

That worked as expected, until I tried to call the previously defined function square
on another line. Is this just an interpreter thing or is there more work involved in calling functions in the real Haskell world?
Now we’re going to combine it with the map
function.

I did in fact get back what I expected: I mapped the square function across the range 1 to 10. Already I can see why functional programming would be a godsend for Project Euler.
Moving on from function definitions, it looks like we’re going to explore some string manipulation: toUpper
uppercases a single character.

Easy peasy. We’ve hammered home map
and we’ve just shown we can map another function across a range, so a list of characters shouldn’t be any different.
I’ll try map toUpper "Chris"
.

Another lesson bites the dust, and except for some slight, latent ‘suspicion’ about (+1)
and (>5)
being functions (I’m always expecting labels/names like square
out of habit) I feel good so far.
Inventory: I learned the map
function, toUpper
, and how to define my own functions and apply them across ranges and lists.
Confidence Level: Pretty high with some nagging concerns.
Pattern matching is next, and that’s what I’m most excited about!
5. I’ve Made a Huge Mistake

Right up until I tried let (a,b) = (10,12) in map (*2)
I felt I really had it all figured out. I thought: let’s try mapping ‘multiplying by two’ over (a,b).
Here’s a quick summary of my attempts:
let (a,b) = map (*2) (10,12)
let (a,b) = (10, 12) in map (*2)(a,b)
let (a,b) = (10,12) in (a*2, b)
let (a,b) = (10,12) in map *2 (a,b)
let (a,b) = (10,12) in map (*2) (a,b)
let (a,b) = (10,12) in map (*2) [a,b]
actually worked!
I seriously feel like I missed the point, but this kind of thing can only be expected when you go off the rails and try to prove out knowledge to yourself. It just shows how little I really understand how tuples interact with the map
function.
What was I supposed to be doing again?
Right, type in (a:b:c[]) = “xyz” in a,
which I imagine grabs the letter “x” from the string since a
is the first variable in the list of characters.

And all is right with the world again — back on solid ground at least with understanding the convention of picking from a
even if it begs the question on how to get the nth element in a list.
The question gets further begged in the back of my mind while the tutorial teaches me how to ignore everything but the first element in the string.
let (a:_) = "xyz" in a

A new goal: get the 'a'
using pattern matching for (10,"abc")
.
This stumped me immediately as I was unable to see the proper application of the underscore.
Failed line of thought: let (a:_) = (10,"abc") in second
I have no idea what craziness my brain came up with there, especially since I’m pretty sure I only just learned about second
a few slides back as an alternate example (although this did answer a long standing question from when fst
was still introduced) and I didn’t even have an input for second
— I blame learning fatigue.
I skipped ahead to discover the answer.

In retrospect the answer seems really obvious: a tuple containing the ignore construct for the second parameter. I have no idea if that’s correct nomenclature but that’s the closest equivalent I could map it to in my head.
(_,(a:_))
doesn’t have any new, unseen tools — it’s just a construct based on the lessons so far. Fair enough: I failed at my first pattern matching test.
Let’s try the example with the @
operator (or is it a function?).
let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)
I’m going to guess that it should result in:((10,20,30),10,20,30)

That last one wasn’t so bad. I’m unclear on really how @
works of course, but the gist of it made sense and I was able to intuit what was probably going to happen.
Inventory: basic pattern matching, ignoring values, maintaining original values.
Confidence Level: Shaken back down to only somewhat confident.
Conclusion
A bit rough, but it didn’t scare me off. If anything the takeaway feeling was “forewarned” in the sense that I knew there are wide swaths of programming knowledge that are invalid in the functional paradigm.
Plenty of little things tripped me up, some things went unexplained, others would’ve been too large a distraction to explain in the tutorial.
All in all I truly enjoyed the tutorial and will definitely be reading “Learn You a Haskell For Great Good!” as my next step.