class WriterMonad {

	
	private $value;
	
	private $logs;

	private function __construct($value, array $logs = []) {
		$this->value = $value;
		$this->logs = $logs;
	}

	public static function unit($value, string $log): WriterMonad {
		return new WriterMonad($value, []);
	}

	public function bind(callable $mapper): WriterMonad  {
		$mapped = $mapper($this->value);
		assert($mapped instanceof WriterMonad);
		return new WriterMonad($mapped->value, [...$this->logs, ...$mapped->logs]);
	}

	public function value() {
		return $this->value;
	}

	public function logs(): array {
		return $this->logs;
	}
}

$root = fn(float $i): float => sqrt($i);
$addOne = fn(float $i): float => $i + 1;
$half = fn(float $i): float => $i / 2;

$m = fn (callable $callback, string $log): callable => fn ($value): WriterMonad => WriterMonad::unit($callback($value), $log);

$result = WriterMonad::unit(5, )
	->bind($m($root, ))
	->bind($m($addOne, ))
	->bind($m($half, ));

print ;
print join(, $result->logs());