// IO monad: wraps a thunk (deferred computation) struct IO { private let effect: () -> A init(_ effect: @escaping () -> A) { self.effect = effect } // Transform the result without executing func map(_ f: @escaping (A) -> B) -> IO { IO { f(self.effect()) } } func unsafeRun() -> A { effect() } } func rollDiceImpure() -> Int { return Int.random(in: 1...6) } func rollDice() -> IO { IO { rollDiceImpure() } } func allowedToLeaveHome() -> IO { rollDice().map { $0 == 6 } }