2016-06-15 2 views
0

해킹에서 밑줄로부터 reduce 함수를 구현하려고합니다.hacklang에서 여러 일반 유형 결합

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 

가 어떻게이 말할까요 :이 오류가 발생

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; 
} 

: 기능을 구현하는

If no memo is passed to the initial invocation of reduce, the iteratee is not invoked on the first element of the list. The first element is instead passed as the memo in the invocation of the iteratee on the next element in the list.

내 시도 : 밑줄에서 감소 기능은 다음과 같은 문제가 있습니다 유형 검사는 T == Tresult 것을 is_null($memo)

답변

1

가 나는 점에 유의 경우 라인

$memo = $iterable->firstValue(); 

$memoT 타입의 값을 할당한다. 이것은 틀린 것처럼 보인다. $memo은 선언 형 ?Tresult의로 주어지고, 여기 유형 Tresult의 값이 할당됩니다

$memo = $fn($memo, $value); 

$memo이 첫 번째 인스턴스의 유형 T의 값을 할당하는 이유를 설명 할 수 있습니까? TTresult이 같은 것을 어떻게 알 수 있습니까? 나는이 두 종류가 항상 똑같은 것으로 제한된다는 증거가 전혀 없음을 본다. 이 프로그램은 typesafe가 아니기 때문에 유형 검사기가 여기에 오류를 표시합니다. T가 Animal이고 Tresult가 Fruit이고 다른 누군가가 null 과일을 쓴다면 그 순서에서 과일을 얻을 수있는 방법이 없습니다. 또한

, 나는 그것이 이상한 reduce가 널 (NULL) 결과를 반환 것을 발견; 반드시 주어진 결과 유형의 결과를 리턴해야합니다. 그렇지 않습니다. 이 기능은 두 개의 서로 다른 행동이 인수의 무효에 따라 갖고 싶어

, 왜하지 않고 단순히 두 가지 기능을 가지고?

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()); 
} 

이제 우리는 두 가지 다른 형태의 reduce를 가지며 둘 다 타입 안전합니다.

+0

메모를 생략하면 Iterable의 첫 번째 값이 메모로 사용됩니다. 이 경우, T는 Tresult와 동일합니다. 이것은 underscore.js의 reduce()의 동작이며 때때로 교환 가능 작업에 유용합니다. 예를 들면 다음과 같습니다. _.reduce ([1,2,3], (x, y) => x + y) – nwarp

+0

@nwarp : 당신은 나를 따라 다니지 않습니다. ** 당신의 해킹 프로그램에서 타입이 동일하게 **되는 것은 무엇입니까? 무엇이''Fruit'을'$ memo '로,''Giraffe''를 시퀀스에 전달하지 못하게합니까? 타입 시스템은 당신이 * 일어날 수 없다는 어떠한 증거도 제공하지 않았기 때문에 일어날 수 있다고 말하고 있습니다. –

+0

@nwarp : 귀하의 질문은 "이 값이 null 일 때이 두 유형이 같은지 유형 검사기에 어떻게 알려야합니까?"입니다. * 값이 null 인 경우 * 반드시 같을 필요는 없습니다. * 거짓말이기 때문에 타입 검사기에 말할 수 없습니다. –