Last active
April 10, 2020 14:48
-
-
Save marcosh/81a7c224addfeaabc60ee850248139d0 to your computer and use it in GitHub Desktop.
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 | |
declare(strict_types=1); | |
/** | |
* @template F | |
* @template A | |
* @extends Functor<F,A> | |
*/ | |
interface Apply extends Functor | |
{ | |
/** | |
* @template B | |
* @param HK $f | |
* @psalm-param HK<F,callable(A): B> $f | |
* @return HK | |
* @psalm-return HK<F, B> | |
*/ | |
public function apply($f): HK; | |
} |
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 | |
declare(strict_types=1); | |
/** | |
* @template F | |
* @template A | |
* @extends HK<F,A> | |
*/ | |
interface Functor extends HK | |
{ | |
/** | |
* @template B | |
* @param callable $f | |
* @psalm-param callable(A): B $f | |
* @return HK | |
* @psalm-return HK<F, B> | |
* | |
*/ | |
public function map( | |
callable $f | |
): HK; | |
} |
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 | |
declare(strict_types=1); | |
/** | |
* Define Higher Kinded Types following the paper Lightweight Higher Kinded Polymorphism | |
* By Jeremy Yallop and Leo White | |
* https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf | |
* | |
* @template F | |
* @template A | |
*/ | |
interface HK | |
{ | |
} |
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 | |
declare(strict_types=1); | |
/** | |
* @template A | |
* @implements Functor<MaybeBrand, A> | |
*/ | |
final class Maybe implements Functor | |
{ | |
/** @var bool */ | |
private $isJust; | |
/** | |
* @var mixed | |
* @psalm-var A|null | |
*/ | |
private $value = null; | |
/** | |
* @param bool $isJust | |
* @param mixed $value | |
* @psalm-param A|null $value | |
* @psalm-pure | |
*/ | |
private function __construct(bool $isJust, $value = null) | |
{ | |
$this->isJust = $isJust; | |
$this->value = $value; | |
} | |
/** | |
* @template B | |
* @param mixed $value | |
* @psalm-param B $value | |
* @return self | |
* @psalm-return self<B> | |
* @psalm-pure | |
*/ | |
public static function just($value): self | |
{ | |
return new self(true, $value); | |
} | |
/** | |
* @template B | |
* @return self | |
* @psalm-return self<B> | |
* @psalm-pure | |
*/ | |
public static function nothing(): self | |
{ | |
return new self(false); | |
} | |
/** | |
* @template B | |
* @param mixed $ifNothing | |
* @psalm-param B $ifNothing | |
* @param callable $ifJust | |
* @psalm-param callable(A): B $ifJust | |
* @return mixed | |
* @psalm-return B | |
* @psalm-pure | |
*/ | |
public function eval( | |
$ifNothing, | |
callable $ifJust | |
) { | |
if ($this->isJust) { | |
/** @psalm-suppress PossiblyNullArgument */ | |
return $ifJust($this->value); | |
} | |
return $ifNothing; | |
} | |
/** | |
* @template B | |
* @param callable $f | |
* @psalm-param callable(A): B $f | |
* @return HK | |
* @psalm-return HK<MaybeBrand, B> | |
*/ | |
public function map(callable $f): HK | |
{ | |
return $this->eval( | |
Maybe::nothing(), | |
/** | |
* @psalm-param A $value | |
* @psalm-return self<B> | |
*/ | |
fn($value) => self::just($f($value)) | |
); | |
} | |
/** | |
* @template B | |
* @param HK $f | |
* @psalm-param HK<MaybeBrand, callable(A): B> $f | |
* @return HK | |
* @return HK<MaybeBrand, B> | |
*/ | |
public function apply(HK $f) | |
{ | |
/** | |
* @psalm-var Maybe $f the only instance of MaybeBrand is Maybe | |
*/ | |
return $f->eval( | |
self::nothing(), | |
fn($g) => $this->map($g) | |
); | |
} | |
} |
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 | |
declare(strict_types=1); | |
final class MaybeBrand | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment