Last active
May 10, 2019 09:40
-
-
Save harmenjanssen/72e86eb180a1087747a49959899878a1 to your computer and use it in GitHub Desktop.
Quick example of how Maybe could work in PHP.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$record = $model->fetchById(42); // return Maybe(Record) | |
$related = $record->map(function ($record) { | |
// If this function is executed, record is definitely available, no need to check. | |
return $otherModel->fetchWhere('foreign_key', $record->id); | |
}); | |
// It's still a Maybe after mapping, so you can continue mapping on the value. | |
// If the first fetchById call got you a Nothing, this is still the same | |
// Nothing, but your code doesn't need to know, it can be written | |
// optimistically. | |
$justNames = $related->map(function ($rowset) { | |
return $rowset->each(function ($row) { | |
return $row->name; | |
}); | |
}); | |
// At some point you need to pull your value back out of course, for instance | |
// to render in a view, or simply to pass a scalar value to another package | |
// that expects a simple value, not a Functor. | |
// Not sure what interface to use for that, but I've seen "fold" used here: http://www.tomharding.me/2016/12/31/yippee-ki-yay-other-functors/#maybe | |
// Turn Maybe into scalar value to work with in a view, or other service, defaulting to empty list. | |
$justNames = $justNames->fold([]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Model { | |
public function fetchById(int $id): Maybe { | |
$result = $this->databaseAdapter->query( /* query by id */ ); // Returns ?Record | |
return is_null($result) | |
? new Nothing() | |
: new Just($result); | |
} | |
} | |
interface Functor { | |
public function map(callable $fn): Functor; | |
} | |
abstract class Maybe implements Functor { | |
public function __construct($value) { | |
$this->value = $value; | |
} | |
public function map(callable $fn): Functor { | |
return $this instanceof Nothing | |
? $this | |
: new Just($fn($this->value)); | |
} | |
public function fold($default) { | |
return $this instanceof Nothing | |
? $default | |
: $this->value; | |
} | |
} | |
class Just extends Maybe {} | |
class Nothing extends Maybe {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the example, makes it very clear.