Shouldn't IO::bind be lazy?
Consider the following code:
use Chemem\Bingo\Functional\Functors\Monads\IO;
$io = IO::of(function () {
echo 'LOG 1', PHP_EOL;
})
->bind(function () {
return IO::of(function () {
echo 'LOG 2', PHP_EOL;
});
});
It prints LOG 1 even $io->exec() is not called.
Hello, Mr. Popov. IO::bind should not be lazy as it is a faculty for forward function chaining: it acts on the result of the value encapsulated inside the impure operation that exists in the monad's jurisdiction.
In your example, the function prints "LOG 1" because the function supplied to bind acts on a value of null - the return value of the unsafe operation in the monad's context.
Hello, Mr. Popov. IO::bind should not be lazy as it is a faculty for forward function chaining: it acts on the result of the value encapsulated inside the impure operation that exists in the monad's jurisdiction.
Isn't the whole point of IO is to postpone the impure operation (side effect)?
In your example, the function prints "LOG 1" because the function supplied to bind acts on a value of null - the return value of the unsafe operation in the monad's context.
I'm not sure I fully understand what you mean.
I just started to learn and use all these functional things but the samples I've seen in js and typescript libraries are definitely lazy and I thought that they work in the same way no matter what language you use.
Here is an example based on the IO implementation from the Mostly Adequate Guide book: https://jsfiddle.net/alexanderpopov/m4kq2oaw/24/
In the example both console.log will be performed only when io.unsafePerformIO() is called. If you comment the io.unsafePerformIO(); line, console.log('LOG 1') won't be executed.
Here is another example based on fp-ts library:
import { pipe } from 'fp-ts/lib/pipeable';
import { IO, chain } from 'fp-ts/lib/IO';
const log1 = (): IO<void> => () => console.log('LOG1');
const run = pipe(
log1(),
chain(() => () => console.log('LOG2')),
);
run();
It's different from the implementation above but it works in the same way, console.log will be executed only when run() is called.