Skip to content

Instantly share code, notes, and snippets.

@harmenjanssen
Last active May 10, 2019 09:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harmenjanssen/72e86eb180a1087747a49959899878a1 to your computer and use it in GitHub Desktop.
Save harmenjanssen/72e86eb180a1087747a49959899878a1 to your computer and use it in GitHub Desktop.
Quick example of how Maybe could work in PHP.
<?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([]);
<?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 {}
@martijngastkemper
Copy link

Thanks for the example, makes it very clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment