From 5c60d8b7d3a32386249c7c815260d46d1b76a186 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Dec 2024 12:58:44 +0100 Subject: [PATCH] fix Either and Maybe ::memoize() not loading everything --- CHANGELOG.md | 6 ++++++ proofs/either.php | 27 +++++++++++++++++++++++++++ proofs/maybe.php | 20 ++++++++++++++++++++ src/Either/Defer.php | 2 +- src/Maybe/Defer.php | 2 +- 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 proofs/either.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 468634f..3b34c7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Fixed + +- `Innmind\Immutable\Maybe::memoize()` and `Innmind\Immutable\Either::memoize()` was only unwrapping the first layer of the monad. It now recursively unwraps until all the deferred monads are memoized. + ## 5.10.0 - 2024-11-09 ### Added diff --git a/proofs/either.php b/proofs/either.php new file mode 100644 index 0000000..4ab566a --- /dev/null +++ b/proofs/either.php @@ -0,0 +1,27 @@ +filter(static fn($value) => !\is_null($value))), + static function($assert, $value) { + $loaded = false; + $either = Either::defer(static fn() => Either::right($value)) + ->flatMap(static function() use ($value, &$loaded) { + return Either::defer(static function() use ($value, &$loaded) { + $loaded = true; + + return Either::right($value); + }); + }); + + $assert->false($loaded); + $either->memoize(); + $assert->true($loaded); + }, + ); +}; diff --git a/proofs/maybe.php b/proofs/maybe.php index bdff303..1b165aa 100644 --- a/proofs/maybe.php +++ b/proofs/maybe.php @@ -43,4 +43,24 @@ static function($assert, $value1, $value2) { ); }, ); + + yield proof( + 'Maybe::memoize() any composition', + given(Set\Type::any()->filter(static fn($value) => !\is_null($value))), + static function($assert, $value) { + $loaded = false; + $maybe = Maybe::defer(static fn() => Maybe::just($value)) + ->flatMap(static function() use ($value, &$loaded) { + return Maybe::defer(static function() use ($value, &$loaded) { + $loaded = true; + + return Maybe::just($value); + }); + }); + + $assert->false($loaded); + $maybe->memoize(); + $assert->true($loaded); + }, + ); }; diff --git a/src/Either/Defer.php b/src/Either/Defer.php index e962868..fe37f91 100644 --- a/src/Either/Defer.php +++ b/src/Either/Defer.php @@ -108,7 +108,7 @@ private function unwrap(): Either * @psalm-suppress InaccessibleProperty * @psalm-suppress ImpureFunctionCall */ - return $this->value ??= ($this->deferred)(); + return $this->value ??= ($this->deferred)()->memoize(); } /** diff --git a/src/Maybe/Defer.php b/src/Maybe/Defer.php index 09d46a4..251e537 100644 --- a/src/Maybe/Defer.php +++ b/src/Maybe/Defer.php @@ -107,7 +107,7 @@ private function unwrap(): Maybe * @psalm-suppress InaccessibleProperty * @psalm-suppress ImpureFunctionCall */ - return $this->value ??= ($this->deferred)(); + return $this->value ??= ($this->deferred)()->memoize(); } /**