Want to keep learning?

This content is taken from the The University of Glasgow's online course, Functional Programming in Haskell: Supercharge Your Coding. Join the course to learn more.

Skip to 0 minutes and 6 seconds JEREMY: Do you want to know something upsetting? Programs fail. Yes, computation often goes wrong. Haskell provides several mechanisms for handling computations that fail. The first– probably the simplest such mechanism– is called Maybe.

Skip to 0 minutes and 28 seconds Let’s think about how a computation might fail. Imagine trying to process a list somehow. Say, take the first element of the list. And you are given an empty list. There isn’t any first element. Or imagine dividing two integers and the divisor is 0.

Skip to 0 minutes and 51 seconds We need a way to capture whether or not such a computation has succeeded or whether it’s failed. This is the job of Maybe.

Skip to 1 minute and 2 seconds Let’s have a look at this data type. It’s defined in the Haskell prelude. The standard library for Haskell. So here I am in Google. I’m going to type in Haskell prelude and Maybe. Wait for the results. And the first hit is the Hackage site which is the official documentation for the Haskell platform. Let’s click on that. And here we are. Documentation for the prelude standard module. Let’s search in here for Maybe. Here we are. And we see that Maybe represents or encapsulates an optional value. So the value might either be Just a, for some a. Or it’s empty which is Nothing. The documentation goes on to say, using Maybe is a good way to deal with errors or exceptional cases.

Skip to 2 minutes and 0 seconds So these are the type constructors. Either Nothing or Just a. We can look at the source as well. Let’s click here and have a look at the source for Maybe. And this is very familiar to us as an algebraic data type. Similar to the ones that we defined earlier on in the course. Maybe is either Nothing or Just a. For the type variable a. And again, we have these two type classes that Maybe derives. Eq for equality. And Ord for comparison. Right. Let’s have a play with Maybe. Imagine we want a function to find the maximum value in the list. Perhaps a list of integers. Let’s start off by defining the maxhelper routine.

Skip to 2 minutes and 57 seconds So maxhelper is going to take an integer value which is the maximum we’ve seen so far. And an integer list which is the rest of the list we still have to process to look to the maximum value. And it’s going to return an int, which is the maximum value over the whole list. So maxhelper. If we’re given an interim maximum and there’s nothing else left to look at, the list just returns x. That is the maximum. Maxhelper with an interim value x and a nonempty input list is going to call itself recursively.

Skip to 3 minutes and 38 seconds And the interim maximum is either going to be x or y depending on which one is larger. And then we’ll process the rest of the list.

Skip to 3 minutes and 51 seconds So let’s just try this code to see if it works. Sorry. I’m going to start an interactive prompt inside my emacs session and I”m going to run ghci. And I’m going to load max.hs which is where that code is stored. So I can say type maxhelper. There we go there. And I can run it– maxhelper. So if I give it a value to an empty list, it should return that value as the maximum.

Skip to 4 minutes and 29 seconds If I give it a value that’s small, then I give it the list. Right. I’ve said minus 1. So I need to put that inside brackets. That’s interpreted correctly as an integer value. So maxhelper with an interim maximum of minus 1 and a list 1, 2, 3 returns 3, and so on. Let’s go back to the source code now and define a second function, which is called maxfromlist.

Skip to 4 minutes and 58 seconds This is only going to take an integer list and it’s going to return the maximum value in that list. It’s going to use maxhelper to find the maximum value. So maxfromlist. If it’s supplied with an empty list what’s it going to return? I’ve got a problem here. There is no maximum to return. So let’s return nothing. And let’s say our return type has now become Maybe int. Because we can only return an int if there is a maximum. And if there isn’t, we’ll have to return Nothing. Maxfromlist. If there are elements in list then it’s going to return maxhelper. I need an equal sign there. Sorry. Equals maxhelper x. The interim maximum xs– the rest of the list.

Skip to 5 minutes and 56 seconds And I need to wrap this up inside the Maybe. So I need to say it’s going to return Just this integer value. Good. So let’s go back to our ghci session. And let’s say, reload. Which will reload the edited max.hs source code. And now I should be able to say maxfromlist 1 2, 3, And that returns Just 3. Good. If I say maxfromlist empty list it returns Nothing. Great. This works fine. The Maybe type means that the type checker guarantees client code will check the result of the computation. Probably with a case expression. This is much more robust than C error codes.

Skip to 6 minutes and 48 seconds Right. Once we’ve generated Maybe values, how do we propagate them in programs? Perhaps by using lots of case statements. But surely there must be a better way. And there is. At this point I will mumble the word monads. But we’ll cover these in more detail in week six. For now let me show you how you can map functions over Maybe values. So let’s say let function inc equals one plus.

Skip to 7 minutes and 25 seconds So the type of inc in the context of the type variable a that is an instance of the number type class. Then inc takes an a and returns an a. So if I say inc 1 it returns the value 2. How about if I say inc Just 1? Look. It doesn’t work. So inc can’t be applied to Maybe values. However, if I use the fmap function– this is a higher order function here– inc Just 1. I get back Just 2. So fmap allows inc to be applied to the value inside the Maybe. The 1 inside the Just 1. Fmap inc Just 2 returns Just 3. And now you’re saying, what happens if I apply inc 2 Nothing? Guess.

Skip to 8 minutes and 40 seconds I get back Nothing. Great. Let’s leave Maybes there for now. We’ll come back to them and monads in general later in the course. Thanks. Bye.

Dealing with Uncertainty

What do we do when computations fail to generate results? Examples include taking the head of an empty list, or finding the minimum value of a tree which turns out to be a Leaf.

Haskell provides Maybe values, which allow us to denote missing results with Nothing. This is type-safe, so much better than null in C-like languages. Maybe is like Option in Scala.

Share this video:

This video is from the free online course:

Functional Programming in Haskell: Supercharge Your Coding

The University of Glasgow

Get a taste of this course

Find out what this course is like by previewing some of the course steps before you join: