GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

What is a monad?

Swift version: 5.10

Paul Hudson    @twostraws   

A monad is any data type that can be mapped over using map() and flat mapped over using flatMap(), as long it abides by three laws. Arrays, sets, optionals, and more are all monads.

You don’t need to understand (or even be aware of) the three monad laws in order to use them, but if you’re curious I’ll try to explain. The three monad laws are best demonstrated using code, because honestly it’s a bit heavy when you’re just learning.

The first law is left identity, and means that if you have: 1) a value, e.g. the number 5; 2) a monad that contains that value, e.g. an array containing the number 5; and 3) a function that accepts the same type of value (5) and sends back the same type of monad (an array); then calling flatMap() on the array should be equal to applying the function directly to the value.

In code:

// if you have a value, in this case 5
let myNumber = 5

// and you have a monad containing that value, in this case an array containing 5
let myMonad = [myNumber]

// and you have a function that accepts a number and returns the same type of monad as we had before (an array)
let doubleNumbers = { (value: Int) in return [value * 2] }

// then calling flatMap on the array…
let result1 = myMonad.flatMap(doubleNumbers)

// should be equal to applying the function directly to the value
let result2 = doubleNumbers(myNumber)

// so, this should print "true" in a playground
result1 == result2

The second law is right identity, and means that if you have: 1) a value, e.g. the number 5; 2) a monad that contains that value, e.g. an array containing the number 5; and 3) a function that accepts the same type of value (5) and sends back the same kind of monad (an array) without transforming the value; then calling flatMap() with that function on your monad should leave it unchanged.

In code:

// if you have a value, in this case 5
let value = 5

// and you have a monad containing that value, in this case an array containing 5
let array = [5]

// and you have a function that accepts a number and returns the same type of monad as we had before (an array) without transforming the value
let wrapInArray = { (value: Int) in return [value] }

// then calling flatMap() with that function on your monad should leave it unchanged
let flatMapped = array.flatMap(wrapInArray)

// this should print "true" in a playground
array == flatMapped

The third law is associativity, and means that if you have 1) a value, e.g. the number 5; 2) a monad that contains that value, e.g. an array containing the number 5; and 3) two functions that can be run on that monad as a chain; then it shouldn’t matter how those functions are nested.

// if you have a value, in this case 5
let anotherNumber = 5

// and you have a monad containing that value, in this case an array containing 5
let anotherArray = [myNumber]

// and you have two functions that can be run on that monad as a chain, in this case one that multiplies by 5 and one by 10
let multiplyBy5 = { [$0 * 5] }
let multiplyBy10 = { [$0 * 10] }

// then it shouldn’t matter how those functions are nested
let chained = anotherArray.flatMap(multiplyBy5).flatMap(multiplyBy10)
let nested = anotherArray.flatMap { multiplyBy5($0).flatMap(multiplyBy10) }

// this should print "true" in a playground
chained == nested

Again, you don’t need to understand these laws in order to use monads, so don’t be too worried if you understood only part of the code above.

Hacking with Swift+

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and more!

Learn more here

Available from iOS 8.0 – learn more in my book Pro Swift

Similar solutions…

About the Swift Knowledge Base

This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.8/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.