Typing należy zabronić stosowania siebie, to nie powinno być możliwe, aby znaleźć typ dla (t t)
. Jeśli to możliwe, to t
będzie miał typ A -> B
, a my będziemy mieć A = A -> B
. Ponieważ samozastosowanie jest częścią kombinatora Y, nie można go również podać.
Niestety wiele systemów Prolog pozwala na rozwiązanie dla A = A -> B
. Dzieje się tak na wielu podstawach: albo system Prolog zezwala na terminy kołowe, a następnie proces unifikacji powiedzie się, a wynikowe powiązania będą dalej przetwarzane. Lub system Prolog nie zezwala na terminy kołowe, a następnie zależy od tego, czy implementuje sprawdzanie występowania. Jeśli wystąpi zaznaczenie, to zjednoczenie się nie powiedzie. Jeśli sprawdzenie jest wyłączone, to zjednoczenie może się powieść, ale wynikowe wiązania nie mogą być dalej przetwarzane, najprawdopodobniej prowadząc do przepełnienia stosu podczas drukowania lub dalszych unifikacji.
Sądzę więc, że cykliczne ujednolicenie tego typu dzieje się w danym kodzie przez używany system Prolog i zostaje niezauważone.
Jednym ze sposobów rozwiązania tego problemu może być włączenie sprawdzania występowania lub zastąpienie dowolnej z występujących unifikacji w kodzie za pomocą wyraźnego wywołania unify_with_occurs_check/2.
Pozdrowienia
P.S.: Poniższy kod Prolog działa lepiej:
/**
* 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).
Oto kilka biegnie przykładowe:
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)
Więc jeśli ja rozumiem poprawnie, mówisz twierdzenie autora typu dla Y jest rzeczywiście myli, choć możesz zdefiniować jako typ - który prawdopodobnie byłby odpowiedni dla pełnego języka programowania Turinga, ale nie dla systemu logicznego? – rwallace
Zobacz http://en.wikipedia.org/wiki/Simply-typed_lambda_calculus#General_observations – Dario
Tak, na tym właśnie opierałem moje zrozumienie. Właśnie dlatego byłem zdezorientowany stwierdzeniem zawartym w artykule, który łączyłem, z wnioskiem dotyczącym Y, i chciałem się dowiedzieć, czy autor się pomylił, czy też wiedział coś, czego nie zrobiłem. – rwallace