Go Mad For Monads
Warren Seymour
Lead Developer, radify.io
warren@radify.io
@woogoose

Pure Functions
function iAmPure($a, $b, $c) {
/* ... */
return $x;
}- Pass arguments by value
- Only rely on argument values
- No globals
- No $this or static::
- Easy to test/debug
- Cache with memoization
Pure Functions
- file_get_contents($filename)
- mysql_query($query)
- time()
- rand()
Don't try to do anything practical...
Google: "What is a Monad?"
A monad is just a monoid in the category of endofunctors, what's the problem?
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
"Go learn Haskell"
"Go learn Category Theory"
(M t) → (t → Mu) → (M u)
Crockford's Paradox
"Monads are cursed...

Once you fully understand and appreciate Monads...
You lose the ability to explain them to other people."
Douglas Crockford
The Loophole
- I don't fully understand them
- I will share what I've learned so far
- You fill in the blanks
- Monads are a loophole in the 'functional contract'
- A way to write practical, pure functions
Fundamentals: unit & bind
function unit($value) function bind($monad, function($value) { ... })
- Three functions:
- $value passed to function in bind === $value passed to unit
- All return a new monad.
- Function that returns a new thing === constructor
- All Monads are constructors
- Not all constructors are Monads
Axioms of Monads
1. bind(unit($value), $fn) === $fn($value);
2. bind($monad, unit) === $monad;
3. bind(bind($monad, $fnA), $fnB) === bind($monad, function($value) { return bind($fnA($value), $fnB); });
Go-OO
- Consider Monad a class
- Antithetical to FP?
- Typeclass?
- Make unit a sugared constructor:
-
$monad = Monad::unit($value)
-
- Make bind a class method:
-
$monad->bind($fn)
-
Axioms of class Monad
1. Monad::unit($value)->bind($fn) === $fn($value);
2. $monad->bind(Monad::unit) === $monad;
3. $monad->bind($fnA)->bind($fnB) === $monad->bind(function($value) { return $fnA($value)->bind($fnB); });
Implementation
class Monad {
protected $_value;
public function __construct($value) {
$this->_value = $value;
}
public static function unit($value) {
return new static($value);
}
public function bind($fn) {
$result = $fn($this->_value);
return static::unit($result);
}
}'Wrap' our value
Constructor sugar
Satisfy Axioms 1 and 3
Some tweaks...
/* ... */
public static function unit($value) {
if ($value instanceof self) {
return $value;
}
return new static($value);
}
public function value() {
return $this->_value;
}
/* ... */Back to reality...
Satisfy Axiom 2
Live coding #1!
Monads Everywhere!
// Promises
$http.get('/api/products')
.then(function(products) {
return _.pluck(products, 'name');
})
.then(function(names) {
$scope.names = names;
});// jQuery
$('div.foo')
.css('background', 'red')
.css('color', 'white')
.html('hello world!');// Lodash/Underscore:
_(value)
.filter({category: 'book'})
.sortBy('price')
.reverse()
.value();// Doctrine QueryBuilder
$qb->select('u')
->from('User', 'u')
->where('u.id = ?1')
->orderBy('u.name', 'ASC')
->setParameter(1, 100);"What is a musical instrument?"
- Monads are a category of design patterns
- They come in different flavours:
- Identity ✓
- Maybe
- List
- IO
- Deferred aka Promise
- ...more
Call me 'Maybe'
- Sorry
- Handle potential nulls
-
if ($x === null) return;
-
public function grandParentName() {
return $this
->parent()
->parent()
->name;
}public function grandParentName() {
$parent = $this->parent();
if ($parent === null) {
return;
}
$grandParent = $parent->parent();
if ($grandParent === null) {
return;
}
return $grandParent->name;
}Implementation
class Maybe extends Monad {
public function bind($fn) {
if ($this->_value === null) {
return $this;
}
return parent::bind($fn);
}
}The last null check you'll ever write
... maybe
Live coding #2!
Maybe extend it
/* ... */
public function call($name) {
return $this->bind(function($value) use ($name) {
return $value->name();
});
}
public function prop($name) {
return $this->bind(function($value) use ($name) {
return $value->prop;
});
}
/* ... */Method caller
Property getter
Conclusion
- Monads are a category of design pattern
- We've been using them for years!
- Most common forms: simple implementation
- Haskell and strong mathematical knowledge are not required
- You should still give Haskell a try!
- Go play!
Resources
- Douglas Crockford: Gonads and Monads
- https://www.youtube.com/watch?v=dkZFtimgAcM
- Anthony Ferrara: Taking Monads to OOP PHP
- http://blog.ircmaxell.com/2013/07/taking-monads-to-oop-php.html
-
Learn You a Haskell
- http://learnyouahaskell.com/
Questions
Go Mad For Monads
By Warren Seymour
Go Mad For Monads
Monads in PHP. Why not?
- 3,099