Skip to main content Accessibility help
Internet Explorer 11 is being discontinued by Microsoft in August 2021. If you have difficulties viewing the site on Internet Explorer 11 we recommend using a different browser such as Microsoft Edge, Google Chrome, Apple Safari or Mozilla Firefox.

Chapter 12: Monads and more

Chapter 12: Monads and more

pp. 153-176

Authors

, University of Nottingham
Resources available Unlock the full potential of this textbook with additional resources. There are Instructor restricted resources available for this textbook. Explore resources
  • Add bookmark
  • Cite
  • Share

Summary

In this chapter we increase the level of generality that can be achieved in Haskell, by considering functions that are generic over a range of parameterised types such as lists, trees and input/output actions. In particular, we introduce functors, applicatives and monads, which variously capture generic notions of mapping, function application and effectful programming.

Functors

All three new concepts introduced in this chapter are examples of the idea of abstracting out a common programming pattern as a definition. We begin by reviewing this idea using the following two simple functions:

inc :: [Int] -> [Int]

inc [] = []

inc (n:ns) = n+1 : inc ns

sqr :: [Int] -> [Int]

sqr [] = []

sqr (n:ns) = n^2 : sqr ns

Both functions are defined in the same manner, with the empty list being mapped to itself, and a non-empty list to some function applied to the head of the list and the result of recursively processing the tail. The only important difference is the function that is applied to each integer in the list: in the first case it is the increment function (+1), and in the second the squaring function (^2). Abstracting out this pattern gives the familiar library function map,

map :: (a -> b) -> [a] -> [b]

map f [] = []

map f (x:xs) = f x : map f xs

using which our two examples can then be defined more compactly by simply providing the function to be applied to each integer:

inc = map (+1)

sqr = map (^2)

More generally, the idea of mapping a function over each element of a data structure isn't specific to the type of lists, but can be abstracted further to a wide range of parameterised types. The class of types that support such a mapping function are called functors. In Haskell, this concept is captured by the following class declaration in the standard prelude:

class Functor f where

fmap :: (a -> b) -> f a -> f b

That is, for a parameterised type f to be an instance of the class Functor, it must support a function fmap of the specified type.

About the book

Access options

Review the options below to login to check your access.

Purchase options

eTextbook
US$47.00
Paperback
US$47.00

Have an access code?

To redeem an access code, please log in with your personal login.

If you believe you should have access to this content, please contact your institutional librarian or consult our FAQ page for further information about accessing our content.

Also available to purchase from these educational ebook suppliers