Skip main navigation

Dealing with Uncertainty

Sometimes computations do not generate expected results. Such functions can return Maybe values, as Jeremy Singer explains in this video.
6.4
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.
28.2
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.
51.3
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.
62.3
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.
120.1
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.
177
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.
218.2
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.
231.3
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.
268.6
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.
298
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.
355.5
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.
408.1
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.
444.6
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.
520.2
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.

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.

This article is from the free online

Functional Programming in Haskell: Supercharge Your Coding

Created by
FutureLearn - Learning For Life

Our purpose is to transform access to education.

We offer a diverse selection of courses from leading universities and cultural institutions from around the world. These are delivered one step at a time, and are accessible on mobile, tablet and desktop, so you can fit learning around your life.

We believe learning should be an enjoyable, social experience, so our courses offer the opportunity to discuss what you’re learning with others as you go, helping you make fresh discoveries and form new ideas.
You can unlock new opportunities with unlimited access to hundreds of online short courses for a year by subscribing to our Unlimited package. Build your knowledge with top universities and organisations.

Learn more about how FutureLearn is transforming access to education