2014-10-31 6 views
1

수성에서 람다가 람다를 포함하는 술어의 모드와 동일한 결정론을 가지고 있다고 선언 할 수 있습니까?수성에서 람다와 술어의 일치 결정

다음은 내가하려는 일입니다. array2d 유형에서 작동하는 fold 함수 (아래)를 작성했습니다. fold은 배열의 각 요소에 대해 호출자가 제공 한 술어를 호출합니다. 그것은 det (술어)를 인수로 받아 들일 때까지 잘 작동합니다.

:- pred fold(array2d(T), pred(T, int, int, A, A),    A, A). 
:- mode fold(in,   pred(in, in, in, in, out) is det,  in, out) is det. 
% Uncommenting the next line causes mode errors during compilation 
% :- mode fold(in,  pred(in, in, in, in, out) is semidet, in, out) is semidet. 

fold(Array, Pred, !Accumulator) :- 
    bounds(Array, NumRows, NumCols), 

    FoldRows = (pred(RowNumber :: in, RowAccIn :: in, RowAccOut :: out) is det :- 
     FoldCols = (pred(ColNumber :: in, ColAccIn :: in, ColAccOut :: out) is det :- 
      Value = Array^elem(RowNumber, ColNumber), 
      Pred(Value, RowNumber, ColNumber, ColAccIn, ColAccOut) 
     ), 
     int.fold_up(FoldCols, 0, NumCols - 1, RowAccIn, RowAccOut) 
    ), 
    int.fold_up(FoldRows, 0, NumRows - 1, !Accumulator). 

그러나 나는 DET 또는 semidet 조건 중 하나를 동의 (그리고 술어에 대한 호출이 실패 할 경우 실패)에 fold를 원한다. mode ... is semidet 행의 주석 처리를 제거하면 해결 방법을 모르는 컴파일러 오류가 발생합니다. 문제는 fold의 람다가 det로 선언되었으므로 semid를 Pred으로 부를 수 없다는 것입니다. lambda를 semidet으로 변경하면 fold은 전체적으로 det 할 수 없습니다.

어떻게 해결할 수 있습니까? 람다가 fold 술어에서 결정론을 상속 받았다고 선언하는 것이 가장 직접적인 방법 인 것처럼 보입니다. 따라서 fold이 det와 마찬가지로 semidet에 사용되는 경우에는 det가됩니다. 그러나 가능하면 그럴 수 있습니다. .

다른 접근법은 물론 FoldRowsFoldCols을 다중 모드가있는 명명 된 술어 (람다가 아님)로 변환하는 것입니다. 그러나 그것은 신속하게 비 효과적이되고, 나는 더 간단한 해결책이 있는지 궁금해하고 있습니다.

답변

1

수은 때로는 술어의 모드와 결정을 추측 할 수 있으므로 처음에는 람다 식에서 결정론 선언을 생략하여이 문제를 시도했습니다. 그러나 수성의 람다 구문을 사용하면이 작업을 수행 할 수 없으므로 람다에서는이 추론을 사용할 수 없습니다.

나는 FoldRows와 FoldCols를 다중 moded named predicates로 바꾸는 것이 유일한 해결책이라는 것을 두려워하고 있습니다.