/** * @dataProvider provideData */ public function test_demonstrate_state_monad($expectedProducts) { $initialState = new InMemoryCache([]); list($result1, $outputState1) = S\runState(searchRelated('asia'), $initialState); $this->assertEquals($expectedProducts, $result1); list($result2, $outputState2) = S\runState(searchRelated('asia'), $outputState1); $this->assertEquals($expectedProducts, $result2); // After second computation, state shouldn't be modified // Because we have item already in cache $this->assertSame($outputState1, $outputState2); }
/** * doo :: State IO m => [m a] -> m a * * Haskell like "do notation" simple implementation. * Since "do" is reserved keyword in PHP then I use "doo". * * @param array|M\IO[] $monads * * @return M\IO */ function doo(array $monads) { return M\IO::of(function () use($monads) { $result = null; $data = []; // TODO do it by foldWithKeys foreach ($monads as $key => $monad) { // TODO do it better - maybe? if ($monad instanceof M\IO) { $monad = ioState($monad); } $state = [$key, $data]; list($result, list(, $data)) = M\State\runState($monad, $state); } return $result; }); }