我试图在hack中实现下划线中的减值函数。在下划线中,还原函数具有以下行为:
如果没有将备注传递给初次调用reduce,则不会在列表的第一个元素上调用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)
发布于 2016-06-15 16:19:51
我注意到
$memo = $iterable->firstValue();将T类型的值分配给$memo。这似乎是错误的;在声明中,$memo被赋予?Tresult类型,并在这里分配了一个Tresult类型的值:
$memo = $fn($memo, $value);您能解释为什么在第一个实例中为$memo分配一个T类型的值吗?你怎么知道T和Tresult是一样的?我看不出有任何证据表明这两种类型永远是同一回事。类型检查器在这里给出了一个错误,因为这个程序不是类型错误;如果T是动物,而结果是果树,并且有人传入一个空的水果,那么就没有办法从序列中得到一个水果。
而且,我觉得奇怪的是,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());
}在这里,现在我们有两种不同的减缩形式,它们都是典型的。
https://stackoverflow.com/questions/37840497
复制相似问题