- 5 minutes
The first part of this course focused on the Haskell language – but just like learning a foreign language, you can’t become fluent in it without a lot of practice. The best way to become fluent in a foreign language is to speak it a lot, and especially to have conversations. The best way to become fluent in Haskell is to try writing a lot of functions and have conversations with GHCi. This part of the course is going to get you busy doing those things.
Palindromes
We’re going to write a small interactive program, with just a few functions in it, that checks to see if a word that the “user” inputs is a palindrome.
A palindrome is a word that is spelled the same forward and backward, for example, “mom”, or everyone’s favorite: “tacocat”.
We can write a function in Haskell that checks to see if a String
is a palindrome. We’re going to call it isPalindrome
. It will test a String
and give us a yes or no answer.
A word is a palindrome if it is the same as the reverse of that word.
We’re going to be building on this basic function over the course of this session, so you should write this into your file – the main.hs
file or whatever you want to call it. The name of that file isn’t important as long as we make sure that we load it into GHCi.
List reversal
Now, reverse
API documentation for reverse
is a function that is given to us by the Prelude
module that we mentioned previously, that standard set of functions and types that gets loaded automatically. Let’s look at the type of that function in the REPL.
To query the type of a function, we can use this :type
command.
λ> :type reverse
reverse :: [a] -> [a]
We could also abbreviate that as just :t
.
λ> :t reverse
reverse :: [a] -> [a]
We can see that reverse
has the type [a] -> [a]
. That means that it takes in a list of absolutely anything. It could be a list of integers, list of booleans, or a list of good dogs; this function doesn’t care. And it returns a list of the same type. So if we give it a list of Integer
, it will give us back a list of Integer
. If we give it a list of dogs, it will give us back a list of dogs.
Strings are lists
We said that we could use this with a String
in our isPalindrome
function, even though we just saw that it has to take a list.
We can use the :info
command in GHCi to look at what a String
is.
λ> :info String
type String = [Char]
A String
is defined as a type synonym, also called a type alias, for a list of characters.The type
keyword is used to declare type synonyms.
This isn’t super important; it’s a way of giving a new name to a specialization of an already-existing type, so instead of having to write [Char]
, if we prefer, we can write the word String
, and they mean exactly the same thing.
Let’s try out this reverse
function a few times to make sure we’re comfortable with what it does. We can reverse a list of numbers.
λ> reverse [1, 2, 3, 4]
[4,3,2,1]
We can reverse a list of characters, also known as a string.
λ> reverse "Julie"
"eiluJ"
We can even reverse a list of lists, so here are some very good dogs.
λ> reverse ["Alonzo", "Melman", "Dallas"]
["Dallas","Melman","Alonzo"]
We notice that only the top level gets reversed, so ["Alonzo", "Melman", "Dallas"]
reverses to ["Dallas", "Melman", "Alonzo"]
. Even though each element of that list is itself a list, the characters within those words don’t get reversed.
Experiment with isPalindrome
Next let’s try out the isPalindrome
function that we wrote. It only needs one input string – for example, “mom”, which should be a palindrome.
λ> :load main.hs
λ> isPalindrome "mom"
True
And our program confirms it.
Next we see that “tacocat” is also a palindrome, but “Chris” is, sadly, not a palindrome.
λ> isPalindrome "tacocat"
True
λ> isPalindrome "Chris"
False
So far, so good!
If you like, see if you can come up with inputs to this that we would normally consider palindromes but that this function rejects. For example, consider capitalization, whether we think that a capital letter should be considered the same as a lowercase letter in this; or, the word “tacocat” is really two words, ‘taco’ and ‘cat’ – try putting a space in between them as the input to this function and see what it does.