You want to get started with Haskell in a quick and engaging way, without having to start with a long lecture on syntax. So, to develop your familiarity with Haskell, you'll explore some of the basics, such as how to use and manipulate numbers and strings using GHCi, the interactive interpreter.
- [Instructor] Welcome to section two, getting started with Haskell. In this section, we're going to learn about the basics of Haskell, its data types, and its functions by interacting with it in the interpreter, GHCi. We're going to do this in quite a practical hands-on way. We will cover some theory, naturally, as we discover new concepts and ideas. But we're not going to spend a lot of time discussing theory upfront. So, let's have a look at the kind of thing that we'll be covering.
So we'll see how to launch the interpreter using stack ghci. We'll look at a little bit at just a few of the most important built-in data structures, like lists and tuples, and so on. We're going to edit Haskell source code and see how we can use both our text editor and the interactive interpreter to help us develop. We'll start to define our own functions and see how we can build our own data structures. And finally, we'll have a very quick look at pattern matching.
In this video, Discovering Haskell with GHCi, we'll learn how to launch the interactive interpreter and discover Haskell's powerful data types. So, in volume one, we installed Haskell using a tool called stack. And as we can see, stack has many tools which allow you to interact with the version of Haskell that you've installed. Let's use stack ghci to run the interpreter.
As we can see, this opens up a version of Haskell. In my case, 801. You will, of course, open whichever version you've installed in your project. So in this interpreter, we can type in any expression, such as a simple number or a calculation. We could type in a string. Or an operation that can concantenate two strings.
There are also various built-in expressions, like the constant pi. And of course, we can type in floating point numbers and Boolean values such as true and false. Now Haskell is well known for having a powerful type system. And of course, what that means is that all of these values, not just the results like false and true or 1.5 or 3.14, et cetera have a value, but also each component within an expression.
Within the interpreter, we can discover the types of any value by using the command colon type. Now this isn't a Haskell function, this is part of GHCi itself. So if we try type true, we can see that it is a Bool, or Boolean value. And of course, the same holds for type false. And similarly, if we try type pi, we can see that it's a floating number.
And we notice this oddity here, floating a. We'll come back to that later. If we look at type 123, we have a very similar thing. In this case, num. And we might have thought that that would have been an integer. So, let's dig into these things. So, as well as the type command, there is an info command that we can use to get information about various things, and in particular, the types of values.
So, for example, with Booleans, we can ask for info Bool. And we can see the definition data Bool is false or true. And we can see various instances, such as bounded, enum, eq, ord, read, and show. Now we'll look into what those mean in a little while. If we ran info floating, we'd see that there are two types of floating values, float and double.
And so what that suggests is that the reason that pi had a type variable here of a is that pi is a function that could return a floating value of pi, or a double precision floating value of pi. So let's have a look at the number types. We can see that the number 123 is of type num, but with this interesting parameter t.
If we look at the info of the number class, we do see that num has various instances, which can be integers or floating values. It also has a list of operations. Addition, subtraction, multiplication. But interestingly, not division. If we try adding the numbers, we can see that we can add two integers together. And we can add two floating point numbers together. Let's see what happens if we add an integer to a floating point number.
And it turns out, we do actually get a result. So let's see, what type that result has. And here you can see it has a type fractional. And fractional, of course, is another sub-class of number, and it turns out that it's fractional that has the division operator on it. Which makes sense. So the interesting thing is that null 0.5, which is already interpreted as a fractional type, which includes, of coures, float and double, is more specific than the number 123, which is simplY a number.
When you try to add them together, Haskell infers that you wanted to treat 123 as a fractional. So, for example, you can tell Haskell that you want to treat a value in a certain way. And let's look at what happens if we try to add values of different sorts. And here we get a type error because we've tried to add two numbers of different sorts together.
And because the type of addition only allows you to add numbers of exactly the same sort. So, this shows you some of the power and richness of Haskell's numeric system, but also potentially, some of the frustrations that you might have when doing mathematical calculations of making sure that all of your values are in exactly the right type in order to be able to combine them together and perform calculations on them.
So it's a very good idea to do some experiments in GHCi using the number classes, and to see what kind of things you can do with them. So let's have a look at the Boolean class. We can see here that Boolean can be either false or true. And we can also see various instances. So let's have a look at those instances. For example, eq.
We can see that there are many, many classes of eq. And that it provides equality operators. So we should be able to, for example, check whether false is true, false is false, true is true, and so on. We can also invert those types using the not operator. Let's get some more information about not.
And we can also combine Booleans using Boolean logic. And let's have a look at strings. Interestingly, though we call that a string, Haskell has returned us char surrounded in square brackets. And square brackets in many languages, including Haskell, imply a list of values.
So, let's try a string in single quotes. And this is fine, but a longer string in single quotes gives us a rather interesting error. And the reason for this is that a string using single quotes represents a single character. And in fact, a string in double quotes is simply a list of multiple of those single characters. And what that suggests as well is that we might be able to build up our string using list notations.
And in fact, we can do that. And when we do, Haskell special cases the way that it shows that value, by placing it in double quotes, rather than showing it as a comma-separated array. Now there's also a type string. And if we get information about that, we can see that it's simply an alias for a list of chars.
So, we can treat a string as type string quite happily. And because a string is an array, we can also call any array operation on it. So for example, we can go length , and we can get the head and the tail of the string. A common concept in many languages is the idea of the undefined value. Let's try that in Haskell. And we can see that, when an undefined value is used, it causes an exception, which is quite extreme compared to many other programming languages which allow you to use an undefined value.
But in fact, so does Haskell. So, if for example, you declare a variable as undefined, Haskell is perfectly happy to do that. And let's see what would happen if we added these two variables. One an undefined. Now isn't that fascinating? If we look at the type of c, we can see that Haskell has concluded that it must be a number because we're doing addition, which can only be done on numbers.
With a number on the right-hand side and what must be a number on the left-hand side. Being undefined means it that could be anything at all. So, this variable typechecks as a number and compiles perfectly happily. Of course, if we now attempt to evaluate that number, it will end up being an undefined value, and that will cause an exception. In general in Haskell, you try to avoid using undefined values as much as possible.
So before moving on to the next video, I strongly recommend using GHCi and exploring its data types and also its commands. If you're type in help, you will see a whole load of options, but primarily the type and the info commands are really useful. So, explore these data types as much as possible.
It's very hard to get into any kind of catastrophic problem, unless you're trying very, very hard indeed. In the next video, we will look at the built-in data structures within Haskell.
Note: This course was created by Packt Publishing. We are pleased to host this training in our library.
- Discovering Haskell with GHCI
- Haskell datatypes and functions
- Using higher order functions for data manipulation and code reuse
- Editing Haskell source code
- Creating a project with Stack
- Writing and conducting tests