bingo-functional
bingo-functional copied to clipboard
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.