object(PolynomialFunctors\Polynomial)#1 (2) {
["tag":"PolynomialFunctors\Polynomial":private]=>
int(0)
["value":"PolynomialFunctors\Polynomial":private]=>
NULL
}
object(PolynomialFunctors\Polynomial)#5 (2) {
["tag":"PolynomialFunctors\Polynomial":private]=>
int(1)
["value":"PolynomialFunctors\Polynomial":private]=>
int(10)
}
object(PolynomialFunctors\Polynomial)#6 (2) {
["tag":"PolynomialFunctors\Polynomial":private]=>
int(2)
["value":"PolynomialFunctors\Polynomial":private]=>
array(2) {
[0]=>
int(4)
[1]=>
int(8)
}
}
Last active
September 28, 2024 18:32
-
-
Save ghostwriter/0882ad50ac55776ba2e22eb4b563398c to your computer and use it in GitHub Desktop.
Polynomial Functors 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 | |
interface Functor | |
{ | |
/** | |
* Maps a function over the functor. | |
* | |
* @template A | |
* @template B | |
* @param callable(A): B $f | |
* @return Functor<B> | |
*/ | |
public function map(callable $f): Functor; | |
} |
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 | |
$unit = Polynomial::unit(); // Represents `1` | |
$linear = Polynomial::linear(5); // Represents `x` | |
$quadratic = Polynomial::quadratic(3, 7); // Represents `x^2` | |
// Mapping over the functor | |
$mappedLinear = $linear->map(static fn(int $x): int => $x * 2); // Maps over the single value | |
$mappedQuadratic = $quadratic->map(static fn(int $x): int => $x + 1); // Maps over both values | |
// Output results | |
var_dump($unit); // Nothing to map | |
var_dump($mappedLinear); // Polynomial with value 10 | |
var_dump($mappedQuadratic); // Polynomial with values 4 and 8 |
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 #BlackLivesMatter - github.com/ghostwriter | |
namespace PolynomialFunctors; | |
use InvalidArgumentException; | |
/** | |
* Represents a polynomial functor of the form `1 + x + x^2`. | |
* | |
* @template T | |
* @implements Functor<T> | |
*/ | |
final class Polynomial implements Functor | |
{ | |
private int $tag; | |
private mixed $value; | |
private function __construct(int $tag, mixed $value = null) | |
{ | |
$this->tag = $tag; | |
$this->value = $value; | |
} | |
/** | |
* Represents the `1` case. | |
* | |
* @return self | |
*/ | |
public static function unit(): self | |
{ | |
return new self(0); | |
} | |
/** | |
* Represents the `x` case with one value. | |
* | |
* @template T | |
* @param T $value | |
* @return self<T> | |
*/ | |
public static function linear(mixed $value): self | |
{ | |
return new self(1, $value); | |
} | |
/** | |
* Represents the `x^2` case with two values. | |
* | |
* @template T | |
* @param T $first | |
* @param T $second | |
* @return self<T> | |
*/ | |
public static function quadratic(mixed $first, mixed $second): self | |
{ | |
return new self(2, [$first, $second]); | |
} | |
/** | |
* Maps a function over the polynomial structure. | |
* | |
* @template A | |
* @template B | |
* @param callable(A): B $f | |
* @return self<B> | |
*/ | |
public function map(callable $f): Polynomial | |
{ | |
return match ($this->tag) { | |
0 => self::unit(), | |
1 => self::linear($f($this->value)), | |
2 => self::quadratic($f($this->value[0]), $f($this->value[1])), | |
default => throw new InvalidArgumentException('Unknown polynomial tag') | |
}; | |
} | |
} |
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); | |
use PHPUnit\Framework\TestCase; | |
use PolynomialFunctors\Polynomial; | |
final class PolynomialTest extends TestCase | |
{ | |
public function testUnit(): void | |
{ | |
$unit = Polynomial::unit(); | |
$this->assertInstanceOf(Polynomial::class, $unit); | |
$this->assertNull($unit->getValue()); | |
} | |
public function testLinearMapping(): void | |
{ | |
$linear = Polynomial::linear(5); | |
$mapped = $linear->map(fn(int $x): int => $x * 2); | |
$this->assertSame(10, $mapped->getValue()); | |
} | |
public function testQuadraticMapping(): void | |
{ | |
$quadratic = Polynomial::quadratic(3, 7); | |
$mapped = $quadratic->map(fn(int $x): int => $x + 1); | |
$this->assertSame([4, 8], $mapped->getValue()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment