タイピングは自己適用を禁止する必要があり、 のタイプを見つけることができないようにする必要があります(t t)
。可能であればt
、 type を持ち、A -> B
を持ちA = A -> B
ます。自己適用は Y コンビネーターの一部であるため、型を与えることもできません。
残念ながら、多くの Prolog システムでは、A = A -> B
. これは多くの理由で発生します。Prolog システムで循環項が許可されているか、統合が成功し、結果のバインディングをさらに処理することができます。または、Prolog システムが循環項を許可しない場合は、発生チェックを実装するかどうかによって異なります。発生チェックがオンの場合、統合は成功しません。発生チェックがオフの場合、統合は成功する可能性がありますが、結果のバインディングはそれ以上処理できず、印刷またはさらなる統合でスタック オーバーフローが発生する可能性が高くなります。
したがって、このタイプの循環統合は、使用されている Prolog システムによって特定のコードで発生し、気付かれないと思います。
この問題を解決する 1 つの方法は、発生チェックを有効にするか、コード内で発生している統合を unify_with_occurs_check/2 への明示的な呼び出しに置き換えることです。
よろしくお願いします
PS: 次の Prolog コードの方がうまく機能します。
/**
* Simple type inference for lambda expression.
*
* Lambda expressions have the following syntax:
* apply(A,B): The application.
* [X]>>A: The abstraction.
* X: A variable.
*
* Type expressions have the following syntax:
* A>B: Function domain
*
* To be on the save side, we use some unify_with_occurs_check/2.
*/
find(X,[Y-S|_],S) :- X==Y, !.
find(X,[_|C],S) :- find(X,C,S).
typed(C,X,T) :- var(X), !, find(X,C,S),
unify_with_occurs_check(S,T).
typed(C,[X]>>A,S>T) :- typed([X-S|C],A,T).
typed(C,apply(A,B),R) :- typed(C,A,S>R), typed(C,B,T),
unify_with_occurs_check(S,T).
いくつかの実行例を次に示します。
Jekejeke Prolog, Development Environment 0.8.7
(c) 1985-2011, XLOG Technologies GmbH, Switzerland
?- typed([F-A,G-B],apply(F,G),C).
A = B > C
?- typed([F-A],apply(F,F),B).
No
?- typed([],[X]>>([Y]>>apply(Y,X)),T).
T = _T > ((_T > _Q) > _Q)