我正在尝试模仿PHP上的Monad,我无法理解我写的管道功能的输出。
该代码的灵感来自埃里克·埃利奥特(Eric Elliott(的文章。
php -v//php 7.2.19-0 ubuntu0.18.04
<?php
function pipe_map(...$fns) {
return function ($value) use ($fns) {
return array_reduce($fns, function ($prev, $next) {
return $prev->map($next);
}, $value);
};
};
class Maybe {
private $value;
public function __construct($value) {
$this->value = $value;
}
private function doesExist() {
return !empty($this->value);
}
public function map(callable $fn) {
return $this->doesExist()
? new Maybe($fn($this->value))
: new Maybe(NULL);
}
public function join() {
return $this->value;
}
}
$add1 = function ($value) {
return $value + 1;
};
$trace = function ($label) {
return function ($value) use ($label) {
print_r($label . $value . "n");
return $value;
};
};
$mult2 = function ($value) {
return $value * 2;
};
$bad_result = function ($value) {
echo "bad computation happens n";
};
$maybe3 = new Maybe(3);
$result = pipe_map(
$trace("Value is now: "),
$add1,
$trace("Value is now: "),
$bad_result,
$trace("Value is now: "),
$add1,
$trace("Value is now: "),
$mult2,
$trace("Value is now: ")
)($maybe3);
?>
预期的结果是:
Value is now: 3
Value is now: 4
bad computation happens
Value is now:
Value is now:
Value is now:
但是我得到了:
Value is now: 3
Value is now: 4
bad computation happens
我期望调用$bad_result
功能后放置的功能,但显然不是。
打印$result
变量时输出为:
print_r($result);
// Maybe Object
// (
// [value:Maybe:private] =>
// )
var_dump($result->join());
// NULL
一些明亮的灵魂可以照亮我吗?
首先,预期的结果不应该是:
Value is now: 3
Value is now: 4
bad computation happens
Value is now:
Value is now:
Value is now:
这是因为在$bad_result
之后的下一个通话中,您正在调用add1
闭合,该闭合将在您的输出null + 1 = 1
中加1个。
所以预期的结果应该是
Value is now: 3
Value is now: 4
bad computation happens
Value is now:
Value is now: 1
Value is now: 2
这一切都发生了,因为您正在返回new Maybe(NULL);
在您只是不调用错误时,您期望如何在计算错误之后执行回调?
请记住,从$bad_result
回调开始,您要获得的null,因此map
方法的每个调用都将始终执行else
语句,该语句是new Maybe(NULL);
,该语句nothing noth nather。
您需要使用Maybe($fn(null));
,以确保您可以为每个迭代拨打可可。
获得确切的预期结果:
Value is now: 3
Value is now: 4
bad computation happens
Value is now:
Value is now:
Value is now:
您需要在关闭中验证$value
,特别是add1
关闭。
类似:
return !$value ? null : $value + 1;