Haskell: Session 1

As mentioned in my previous blog post, I decided to learn Haskell for my programming class. Why I decided on Haskell? Because mainly the syntax really caught my attention. It’s unlike anything I’ve seen before, and I would definitely like to explore its possibilities. Furthermore, I’ve also heard that Haskell is mostly used in academic situations rather than actual real-life practices, but that won’t stop me from learning such a different language.

The blog posts will be divided into “sessions”. Normally I was planning to do one blog post per day, but due to time restrictions and the high workload of my semester, I might have to cram multiple sessions into one post.

In order to get started, I decided to follow day 1’s instructions according to the book “Seven Languages in Seven Weeks”. I downloaded the Glasgow Haskell Compiler (GHC) from the download (http://www.haskell.org/ghc/), and ran ghci.exe. For now, that’s all I need.

The chapter starts off with very simple instructions using primitive types, inputted into the GHC console. It then transitions to strings & chars, booleans and finally, functions. I won’t go into a lot of details, else this’ll be one hell of a long blog post. There’s how numbers work:

Input: 4
Output: 4

Input: 4 + 1
Output: 5

Input: 4 + 1.0
Output: 5.0

Input: 4 + 2.0 * 5
Output: 14.0

So far, seems simple enough. It’s processing basic math, and once you start using numbers with decimals, it’ll start outputting the result with decimals also. The GHC seems to append decimals only when necessary, not excessively.

Input: 1.0 + 1.0100
Output: 2.01

Order of operations seems to work as expected – based on the real math world. Parentheses are processed properly as well.

Input: 4 * 5 + 1
Output: 21

Input: 4 * (5 + 1)
Output: 24

Onwards to strings and characters. Strings are represented using double quotes:

Input: "Hello"
Output: "Hello"

However, you can’t concatenate strings using “+”. Rather, you have to use “++”.

Input: "Hello" ++ " World"
Output: "Hello World"

Characters are represented using single quotes:

Input: 'a'
Output: 'a'

However, strings really are just built up from an array of characters. From my experience, this is similar to C#.

Input: ['a', 'b']
Output: "ab"

Onwards to booleans. Seems like booleans are expressed using “True” and “False” (without the quotes). Not much can be said about them.

It looks like Haskell is a strongly-typed language. I can’t do something like “1 + True“, or ” “Hello” + 1 “.

Assigning variables to a function in a local scope:

let x = 10

Declaring functions:

 double x = x * 2

Calling said function with a parameter:

double 5

Declaring above function with a type definition, which accepts and returns integers:

double :: Integer -> Integer
double x = x + x

Where the first “Integer” is the accepted parameter, and the second “Integer” being the return type.

Haskell seems to haveĀ pattern matching. From what I understand, it seems to function like some sort of an if/elseif/else construction before the function itself is even called. Here’s an example of a factorial function which at the same time is recursive:

factorial :: Integer -> Integer
factorial 0 = 1
factorial x = x * factorial (x - 1)

To me, this looks like “if the input is 0, then return 1. Else, if the input is anything, execute [code after “x =”]”. The order of the pattern seems to be important. If that third line (which is a “catch-all” pattern) were to be the second line, the pattern would always match said line, rendering the third line for the input “0” useless. I guess it saves you writing if then elses. If you wanted to reverse the pattern matching, you’d useĀ guards:

factorial :: Integer -> Integer
factorial x
    | x > 1 = x * factorial (x - 1)
    | otherwise = 1

The format is basically this:

 | [condition] = [function]

If the condition isn’t satisfied, it’ll continue to the next guard. If that isn’t satisfied, it’ll continue to the next guard, and so on. It seems that you can use it as a base case for recursion as well, which is pretty nice.

Haskell seems to support tuples, which is basically a bunch of variables bundled together. I remember C# having a similar feature also (e.g. “Tuple<int, string>”). It can be used to bundle variables together without making a separate class for them. Tuples in Haskell seems to be bundled in parentheses, like so:

(var1, var2, ...)
(1, "hello")

The feature that I find interesting the most is “list comprehensions”. I’ve never heard of this before. The only way I can describe this is “apply an algorithm to a list”. For example, here is an algorithm which multiplies each element in a list of 1 to 10 by 2:

num = [1..10]
test = [multiplied * 2 | multiplied <- num]

which returns: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Or here is an algorithm which lists all numbers above 5:

num = [1..10]
test = [abovefive | abovefive <- num, abovefive > 5]

which returns: [6, 7, 8, 9, 10]

If I had to write such algorithms in, say, C#, I’d have to start writing LINQ queries or custom iterators which would be a lot of manual work. It’s interesting how you can solve this problem in Haskell with pretty much a single line.

From here on, I’ll skip to the end – the self-study. Else this blog post is going to be even longer.

The self-study results I have included with this post as a zip: Haskell – Day 1

To me, it feels like information about Haskell is all over the place right now. It’s like exploring a strange new world without a map. I’m thinking that I might actually have to make a map – a cheat-sheet – in order to speed up my coding a bit, at least until I get used to the language, else I’ll have to repeatedly look up trivial things I keep forgetting about, such as how to write a function with parameters.

While we’re learning this new language, we also have to think of a programming challenge which could fit the programming language’s problem-solving capabilities very well. I haven’t thought much about it yet, but I had a rather impulsive idea which I think is really funny but cool at the same time – writing an LZ2 decompressor (or a decompressor for some other format). The challenging part would be reading a binary file, reading bits from certain bytes and applying a certain algorithm to the processed data in order to get a decompressed file. I’ll have to look into this to see if it’s actually possible or not, though. I’ll also have to get approval from my instructor. Maybe for testing purposes, I’ll start with an extremely simple compression format which is RLE.

To me, it feels like this blog post is a bit rushed/unstructured, but hopefully, my future posts will be of better quality.

Leave a Reply

Your email address will not be published. Required fields are marked *