我正在尝试从hack中的下划线实现降低功能。在下划线中,减少功能具有以下行为:
如果没有将备忘录传递给最初的降低调用,则不会在列表的第一个元素上调用ITEMERE。相反,第一个元素是作为在列表中下一个元素的iTerateE调用中作为备忘录传递的。
我尝试实现该功能的尝试:
function reduce<T, Tresult>(
Iterable<T> $iterable,
(function(?Tresult, T):Tresult) $fn,
?Tresult $memo=null):?Tresult {
if (is_null($memo)) {
$memo = $iterable->firstValue();
$iterable = $iterable->skip(1);
}
foreach ($iterable as $value) {
$memo = $fn($memo, $value);
}
return $memo;
}
这会导致错误:
Invalid return type (Typing[4110])
This is a value of generic type Tresult
It is incompatible with a value of generic type T
via this generic Tv
我如何告诉类型检查器T == Tresult
is_null($memo)
我注意到该行
$memo = $iterable->firstValue();
将T
类型的值分配给$memo
。这似乎是错误的; $memo
在声明中为?Tresult
类型,并在此处分配了类型Tresult
的值:
$memo = $fn($memo, $value);
您能解释为什么$memo
在一开始就分配了T
类型的值?您怎么知道T
和Tresult
是相同的?我没有看到任何证据表明这两种类型被限制为同一件事。类型的检查器在此处给您一个错误,因为此程序不是TypeAfe;如果T是动物,而Tresult是果实,并且有人通过无效的水果经过,则无法从序列中取出果实。
另外,我发现reduce
返回可无效的结果很奇怪。当然,它应该返回给定结果类型的结果,否?
如果您希望此功能根据参数的无效具有两种不同的行为,那么为什么不简单地具有两个函数呢?
function reduce1<T, Tresult>(
Iterable<T> $iterable,
(function(Tresult, T):Tresult) $fn,
Tresult $memo): Tresult {
foreach ($iterable as $value) {
$memo = $fn($memo, $value);
}
return $memo;
}
function reduce2<T>(
Iterable<T> $iterable,
(function(T, T):T) $fn): T {
return reduce1($iterable->skip(1), $fn, $iterable->firstValue());
}
那里,现在我们有两种不同形式的减少形式,它们都是类型。