Haskell Course - Lesson 4 - Characters, Lists, and Strings

In the last lesson, we got familiar with numeric types. In this lesson, we'll learn about common text types. After this lesson, you'll be able to understand, use, and manipulate text in Haskell easily. Are you ready? Let's go! 💪🔥

Char

Char is the type we use to represent a

Unicode
character.

We write values of type Char (Unicode characters) between single quotes. Like this:

'a'
'5'

Note that if you write a number surrounded by single quotes (like in the last expression), Haskell won't treat it like a number. It will treat it like any other character. So, you can't do math with '7' (with quotes), but you can with 7 (without quotes).

Important: You can only write a single character at a time! This: 'hi' will make your compiler yell at you. And you don't want to start the relationship with your compiler like that. 😅

This one is easy, so we won't waste more time on it.

I know that you want to write more than one character at a time. I get it. You don't want to sound like a freezing caveman. 🥶 But before that, we have to learn about lists.

Lists

Lists are homogeneous

data structures
. This is just a fancy way of saying that they are lists that store elements of the same type.

We represent lists by starting with [, writing the elements separated by ,, and ending with ]. This is an example of a list with three numbers:

[42,404,666]

And this is an example of a list with 5 characters:

['h','e','l','l','o']

In this case, the first element of the list is the Char of value 'h', the second element is the Char of value 'e', and so on.

List type

Important: Lists are homogeneous! That means that you can't have a list with elements of different types! [1,'2',3] will give your compiler a serious migraine! '2' is a character, not a number! You can't have both Int and Char types! You have to choose one or the other!

The type of a list is expressed as the type of the elements that it contains surrounded by squared brackets. A list of type [Int] contains numbers of type Int. A list of type [Char] contains elements of type Char.

You can specify the type of a list the same way you can specify the type of an element. Using the :: operator:

-- Option 1:
[1,2,3] :: [Float] -- Will give you a list of Floats
-- Option 2:
[1 :: Float,2,3]   -- Will give you a list of Floats

In option 1, we indicate that all the numbers are Float.

In option 2, we indicate that only the first number is of type Float. But, because Haskell can infer the types (remember lesson 2), it knows that all the elements are of type Float. How can it tell? If the first element is a Float and all the elements of a list are of the same type, then all elements are Floats.

Keep in mind that you can't specify a type that doesn't fit with the elements. If you have characters as elements and specify a numeric type, you'll get an error.

Usually, it's not needed to specify the type at all. Just let Haskell infer its way through and keep on coding.

We'll see more about lists, but before that, fire up your GHCi, copy and paste the list with 5 characters from before (['h','e','l','l','o']), and hit enter 👀.

That's a String! 😄

Strings

Strings represent lists of characters. You can use the String type to write messages, alphanumeric values, symbols, etc. Unlike Chars, Strings are surrounded with double-quotes like this:

"Hellooooooo!"

"My phone number is 354XXXXXXXX"

"My bank's account password is: NeverGonnaGiveYouUp_NeverGonnaLetYouDown"

Waaaaaaait a minute! You just said that a list of characters is of type [Char]. And now you're telling me that String represents a list of characters? Which is it, you trickster?

— Weirdly angry student? 😂

It's both! 😁 Because String and [Char] are the same type! More specifically, String is

syntactic sugar
for [Char] So, you can use them interchangeably.

What you can't use interchangeably in Haskell are single and double-quotes. Strings (written in double-quotes) are lists of Char (written using single quotes). These are not the same!:

"A" -- String or [Char]
'A' -- Char

The first one is the same as ['A']. And a list that contains the 'A' element is not the same as just the 'A' element!

As you can see, we can write a String with a single character (e.g, "p"), but you can't write a Char with multiple characters (e.g. 'hi').

Courtesy of System32Comics

Now that we're familiar with lists and Strings, let's have some fun!

Fun with Lists

Accessing lists elements

You can access a specific element inside a list by using its index. Every element has an index determined by its position inside the list — starting at 0 (zero).

So, in this case:

['a','b','c']

The index of 'a' is 0, the index of 'b' is 1, and the index of 'c' is 2.

Lists indices start at 0 in almost all programming languages.

Now, how do we access a specific element using the index? By using the !! operator. The !! operator has to be written like this (a list to its left and the index of the element we want to its right):

['a','b','c'] !! 1 -- This will give us 'b'
[12,13,16,18] !! 3 -- This will give us 18

Think about it, and then use GHCi to check your answer. You don't need me to tell you (...kids grow up so fast 😢...).

An error! Because there's no element of index 3. The list ends at index 2 of value 'f'! If you try in GHCi, the compiler will tell you that the index is too large.

Accessing elements sounds wonderful, but what if you have a bunch of lists? Do you have to access them one by one? Well, you could. But you could also concatenate them first! 👀

Concatenation of lists

A common operation with lists is

concatenation
. Imagine that you have a list with January's clients and a list with February's clients, and you want a single list with all the clients. That's when concatenation shines.

We concatenate in Haskell by using the ++ operator. Even though we know that this operator is two + one after the other, Haskell doesn't see it that way. For Haskell, ++ is a single thing! It's an operator that concatenates two lists (and only two lists). Nothing to do with +.

We can use the operator like this (try it out in GHCi):

[1,2,3] ++ [4,5,6] -- [1,2,3,4,5,6]

Exactly! Strings are lists as well, so we can do all the things that we can do with lists.

We can also use the operator as much as needed:

"Hello" ++ " " ++ "World!"

This way, you can create complex messages by combining more simple ones.

Ok, that's it for now. I have to leave something for next week! 😂

We can do many (many many many) more cool things with lists. That's why lists will have their own lesson (maybe two lessons? 🤔, we'll see). For now, make sure to complete this week's homework! 😄

Homework

Solutions for lesson's 3 homework

  • How many ºC is 100 ºF? ➡️ (100 - 32) *5/9 = 37.77ºC
  • How many ºC is 32 ºF? ➡️ (32 - 32) *5/9 = 0ºC
  • How many ºC is 212 ºF? ➡️ (212 - 32) *5/9 = 100ºC

Predict the result of the expressions (use GHCi if needed)

Error! You can't concatenate a lists of different type!

It's 2! The expression to obtain the result is:

([3,7,5,1] ++ [0,5,1,2,9,8,4]) !! 7

Error! You can't concatenate a string with a single character!

By indicating that they are of type Double:

[1,2,3] :: [Double]

or

[1 :: Double ,2,3]

We're done for today! 👏 Next lesson, we'll learn about Booleans and Tuples! Those will be our last types before learning about functions!! 🤩 See you there!!

PD: If you find this course valuable, please share it so more people can learn! 😄