├── .prettierrc ├── composer.json ├── renovate.json └── src ├── Combinator.php ├── Combinator ├── A.php ├── B.php ├── Blackbird.php ├── C.php ├── D.php ├── E.php ├── F.php ├── G.php ├── H.php ├── I.php ├── J.php ├── K.php ├── Ki.php ├── L.php ├── M.php ├── O.php ├── Omega.php ├── Phoenix.php ├── Psi.php ├── Q.php ├── R.php ├── S.php ├── S2.php ├── S_.php ├── T.php ├── U.php ├── V.php ├── W.php ├── Y.php └── Z.php ├── Combinators.php └── Contract └── Combinator.php /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "proseWrap": "always" 3 | } 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loophp/combinator", 3 | "description": "A curated list of combinators", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "combinator", 8 | "combinatory logic", 9 | "educational", 10 | "functional programming" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Pol Dellaiera", 15 | "email": "pol.dellaiera@protonmail.com" 16 | } 17 | ], 18 | "support": { 19 | "issues": "https://github.com/loophp/combinator/issues", 20 | "source": "https://github.com/loophp/combinator" 21 | }, 22 | "funding": [ 23 | { 24 | "type": "github", 25 | "url": "https://github.com/drupol" 26 | } 27 | ], 28 | "require": { 29 | "php": ">= 8.1" 30 | }, 31 | "require-dev": { 32 | "ext-pcov": "*", 33 | "drupol/php-conventions": "^6", 34 | "friends-of-phpspec/phpspec-code-coverage": "^6", 35 | "infection/infection": ">= 0.26", 36 | "infection/phpspec-adapter": "^0.2", 37 | "phpspec/phpspec": "^7", 38 | "phpstan/phpstan-strict-rules": "^1.0" 39 | }, 40 | "autoload": { 41 | "psr-4": { 42 | "loophp\\combinator\\": "./src/" 43 | } 44 | }, 45 | "autoload-dev": { 46 | "psr-4": { 47 | "tests\\loophp\\combinator\\": "./tests/src/" 48 | } 49 | }, 50 | "config": { 51 | "allow-plugins": { 52 | "composer/package-versions-deprecated": true, 53 | "phpstan/extension-installer": true, 54 | "ergebnis/composer-normalize": true, 55 | "phpro/grumphp": true, 56 | "infection/extension-installer": true 57 | }, 58 | "sort-packages": true 59 | }, 60 | "scripts": { 61 | "changelog-unreleased": "auto-changelog -c .auto-changelog -u", 62 | "changelog-version": "auto-changelog -c .auto-changelog -v", 63 | "grumphp": "./vendor/bin/grumphp run", 64 | "infection": "vendor/bin/infection run -j 2", 65 | "phpspec": "vendor/bin/phpspec run -vvv --stop-on-failure" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"] 4 | } 5 | -------------------------------------------------------------------------------- /src/Combinator.php: -------------------------------------------------------------------------------- 1 | __invoke(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Combinator/A.php: -------------------------------------------------------------------------------- 1 | 33 | /** 34 | * @param NewAType $x 35 | * 36 | * @return NewBType 37 | */ 38 | static fn (mixed $x): mixed => $f($x); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Combinator/B.php: -------------------------------------------------------------------------------- 1 | 38 | /** 39 | * @param callable(NewCType): NewAType $g 40 | * 41 | * @return Closure(NewCType): NewBType 42 | */ 43 | static fn (callable $g): Closure => 44 | /** 45 | * @param NewCType $x 46 | * 47 | * @return NewBType 48 | */ 49 | static fn (mixed $x): mixed => ($f)(($g)($x)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Combinator/Blackbird.php: -------------------------------------------------------------------------------- 1 | 38 | /** 39 | * @param NewBType $x 40 | * 41 | * @return Closure(NewAType): NewCType 42 | */ 43 | static fn (mixed $x): Closure => 44 | /** 45 | * @param NewAType $y 46 | * 47 | * @return NewCType 48 | */ 49 | static fn (mixed $y) => ($f)($y)($x); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Combinator/D.php: -------------------------------------------------------------------------------- 1 | 40 | /** 41 | * @param NewAType $x 42 | * 43 | * @return Closure(callable(NewBType): NewCType): Closure(NewBType): NewDType 44 | */ 45 | static fn (mixed $x): Closure => 46 | /** 47 | * @param callable(NewBType): NewCType $g 48 | * 49 | * @return Closure(NewBType): NewDType 50 | */ 51 | static fn (callable $g): Closure => 52 | /** 53 | * @param NewBType $y 54 | * 55 | * @return NewDType 56 | */ 57 | static fn (mixed $y): mixed => (($f)($x))(($g)($y)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Combinator/E.php: -------------------------------------------------------------------------------- 1 | 41 | /** 42 | * @param NewAType $x 43 | * 44 | * @return Closure(callable(NewBType): callable(NewCType): NewDType): Closure(NewBType): Closure(NewCType): NewEType 45 | */ 46 | static fn (mixed $x): Closure => 47 | /** 48 | * @param callable(NewBType): (callable(NewCType): NewDType) $g 49 | * 50 | * @return Closure(NewBType): Closure(NewCType): NewEType 51 | */ 52 | static fn (callable $g): Closure => 53 | /** 54 | * @param NewBType $y 55 | * 56 | * @return Closure(NewCType): NewEType 57 | */ 58 | static fn (mixed $y): Closure => 59 | /** 60 | * @param NewCType $z 61 | * 62 | * @return NewEType 63 | */ 64 | static fn (mixed $z): mixed => (($f)($x))((($g)($y))($z)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Combinator/F.php: -------------------------------------------------------------------------------- 1 | 39 | /** 40 | * @param NewBType $y 41 | * 42 | * @return Closure(callable(NewBType): Closure(NewAType): NewCType): NewCType 43 | */ 44 | static fn (mixed $y): Closure => 45 | /** 46 | * @param callable(NewBType): (Closure(NewAType): NewCType) $f 47 | * 48 | * @return NewCType 49 | */ 50 | static fn (callable $f): mixed => ($f)($y)($x); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Combinator/G.php: -------------------------------------------------------------------------------- 1 | 40 | /** 41 | * @param callable(NewDType): NewBType $g 42 | * 43 | * @return Closure(NewDType): Closure(NewAType): NewCType 44 | */ 45 | static fn (callable $g): Closure => 46 | /** 47 | * @param NewDType $x 48 | * 49 | * @return Closure(NewAType): NewCType 50 | */ 51 | static fn (mixed $x): Closure => 52 | /** 53 | * @param NewAType $y 54 | * 55 | * @return NewCType 56 | */ 57 | static fn (mixed $y): mixed => (($f)($y))(($g)($x)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Combinator/H.php: -------------------------------------------------------------------------------- 1 | 39 | /** 40 | * @param NewAType $x 41 | * 42 | * @return Closure(NewBType): NewCType 43 | */ 44 | static fn (mixed $x): Closure => 45 | /** 46 | * @param NewBType $y 47 | * 48 | * @return NewCType 49 | */ 50 | static fn (mixed $y): mixed => ((($f)($x))($y))($x); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Combinator/I.php: -------------------------------------------------------------------------------- 1 | $x; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Combinator/J.php: -------------------------------------------------------------------------------- 1 | 38 | /** 39 | * @param NewAType $x 40 | * 41 | * @return Closure(NewBType): Closure(NewAType): NewBType 42 | */ 43 | static fn (mixed $x): Closure => 44 | /** 45 | * @param NewBType $y 46 | * 47 | * @return Closure(NewAType): NewBType 48 | */ 49 | static fn (mixed $y): Closure => 50 | /** 51 | * @param NewAType $z 52 | * 53 | * @return NewBType 54 | */ 55 | static fn (mixed $z): mixed => (($f)($x))((($f)($z))($y)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Combinator/K.php: -------------------------------------------------------------------------------- 1 | 33 | /** 34 | * @param NewBType $y 35 | * 36 | * @return NewAType 37 | */ 38 | static fn (mixed $y) => $x; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Combinator/Ki.php: -------------------------------------------------------------------------------- 1 | 33 | /** 34 | * @param NewBType $y 35 | * 36 | * @return NewBType 37 | */ 38 | static fn (mixed $y) => $y; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Combinator/L.php: -------------------------------------------------------------------------------- 1 | static fn (callable $g): mixed => ($f)(($g)($g)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Combinator/M.php: -------------------------------------------------------------------------------- 1 | $f($f); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Combinator/O.php: -------------------------------------------------------------------------------- 1 | 38 | /** 39 | * @param callable(NewAType): NewBType $g 40 | * 41 | * @return NewBType 42 | */ 43 | static fn (callable $g): mixed => ($g)((($f)($g))); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Combinator/Omega.php: -------------------------------------------------------------------------------- 1 | ($f)($f)(($f)($f)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Combinator/Phoenix.php: -------------------------------------------------------------------------------- 1 | 40 | /** 41 | * @param callable(NewDType): NewAType $g 42 | * 43 | * @return Closure(callable(NewDType): NewBType): Closure(NewDType): NewCType 44 | */ 45 | static fn (callable $g): Closure => 46 | /** 47 | * @param callable(NewDType): NewBType $h 48 | * 49 | * @return Closure(NewDType): NewCType 50 | */ 51 | static fn (callable $h): Closure => 52 | /** 53 | * @param NewDType $x 54 | * 55 | * @return NewCType 56 | */ 57 | static fn (mixed $x): mixed => ($f)(($g)($x))(($h)($x)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Combinator/Psi.php: -------------------------------------------------------------------------------- 1 | 39 | /** 40 | * @param callable(NewCType): NewAType $g 41 | * 42 | * @return Closure(NewCType): Closure(NewCType): NewBType 43 | */ 44 | static fn (callable $g): Closure => 45 | /** 46 | * @param NewCType $x 47 | * 48 | * @return Closure(NewCType): NewBType 49 | */ 50 | static fn (mixed $x): Closure => 51 | /** 52 | * @param NewCType $y 53 | * 54 | * @return NewBType 55 | */ 56 | static fn (mixed $y): mixed => ($f)(($g)($x))(($g)($y)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Combinator/Q.php: -------------------------------------------------------------------------------- 1 | 39 | /** 40 | * @param callable(NewBType): NewCType $g 41 | * 42 | * @return Closure(NewAType): NewCType 43 | */ 44 | static fn (callable $g): Closure => 45 | /** 46 | * @param NewAType $x 47 | * 48 | * @return NewCType 49 | */ 50 | static fn (mixed $x): mixed => ($g)((($f)($x))); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Combinator/R.php: -------------------------------------------------------------------------------- 1 | 34 | /** 35 | * @param callable(NewBType): (Closure(NewAType): NewCType) $f 36 | * 37 | * @return Closure(NewBType): NewCType 38 | */ 39 | static fn (callable $f): Closure => 40 | /** 41 | * @param NewBType $y 42 | * 43 | * @return NewCType 44 | */ 45 | static fn (mixed $y): mixed => (($f)($y))($x); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Combinator/S.php: -------------------------------------------------------------------------------- 1 | 39 | /** 40 | * @param callable(NewAType): NewBType $g 41 | * 42 | * @return Closure(NewAType): NewCType 43 | */ 44 | static fn (callable $g): Closure => 45 | /** 46 | * @param NewAType $x 47 | * 48 | * @return NewCType 49 | */ 50 | static fn (mixed $x): mixed => $f($x)($g($x)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Combinator/S2.php: -------------------------------------------------------------------------------- 1 | 40 | /** 41 | * @param callable(NewAType): NewBType $g 42 | * 43 | * @return Closure(callable(NewAType): NewCType): Closure(NewAType): NewDType 44 | */ 45 | static fn (callable $g): Closure => 46 | /** 47 | * @param callable(NewAType): NewCType $h 48 | * 49 | * @return Closure(NewAType): NewDType 50 | */ 51 | static fn (callable $h): Closure => 52 | /** 53 | * @param NewAType $x 54 | * 55 | * @return NewDType 56 | */ 57 | static fn (mixed $x): mixed => $f($g($x))($h($x)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Combinator/S_.php: -------------------------------------------------------------------------------- 1 | 40 | /** 41 | * @param callable(NewBType): NewAType $g 42 | * 43 | * @return Closure(NewBType): NewCType 44 | */ 45 | static fn (callable $g): Closure => 46 | /** 47 | * @param NewBType $x 48 | * 49 | * @return NewCType 50 | */ 51 | static fn (mixed $x): mixed => $f($g($x))($x); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Combinator/T.php: -------------------------------------------------------------------------------- 1 | 33 | /** 34 | * @param callable(NewAType): NewBType $f 35 | * 36 | * @return NewBType 37 | */ 38 | static fn (callable $f): mixed => ($f)($x); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Combinator/U.php: -------------------------------------------------------------------------------- 1 | static fn (callable $g): mixed => $g(($f($f))($g)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Combinator/V.php: -------------------------------------------------------------------------------- 1 | 34 | /** 35 | * @param NewBType $y 36 | * 37 | * @return Closure(callable(NewAType): callable(NewBType): NewCType): NewCType 38 | */ 39 | static fn (mixed $y): Closure => 40 | /** 41 | * @param callable(NewAType): (callable(NewBType): NewCType) $f 42 | * 43 | * @return NewCType 44 | */ 45 | static fn (callable $f): mixed => (($f)($x))($y); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Combinator/W.php: -------------------------------------------------------------------------------- 1 | 33 | /** 34 | * @param NewAType $x 35 | * 36 | * @return NewBType 37 | */ 38 | static fn (mixed $x): mixed => ($f)($x)($x); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Combinator/Y.php: -------------------------------------------------------------------------------- 1 | M::of()( 33 | static fn (callable $loop): Closure => $f( 34 | static fn (...$arguments): mixed => M::of()($loop)(...$arguments) 35 | ) 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Combinator/Z.php: -------------------------------------------------------------------------------- 1 | M::of()( 33 | static fn (callable $f): Closure => $callable( 34 | static fn (): Closure => static fn (...$arguments): Closure => M::of()($f)(...$arguments) 35 | ) 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Combinators.php: -------------------------------------------------------------------------------- 1 |