http://muaddibspace.blogspot.com/2008/01/type-inference-for-simply-typed-lambda.html是Prolog中简单输入的lambda演算的简明定义。
它看起来没问题,但后来他声称要为Y组合器分配一个类型...而在非常真实的意义上,将类型添加到lambda演算的整个目的是拒绝为Y组合器之类的东西分配类型
任何人都可以确切地看到他的错误或 - 更有可能 - 我的误解在哪里?
答案 0 :(得分:7)
Y基本形式的组合子
Y f = (\x -> f (x x)) (\x -> f (x x))
使用文章中提出的简单类型系统无法输入。
还有其他更容易但有意义的例子,无法在该级别上输入:
以此为例。
test f = (f 1, f "Hello")
这显然适用于test (\x -> x)
,但我们无法提供此处所需的排名更高的类型,即
test :: (∀a . a -> a) -> (Int, String)
但是即使在像Haskell的GHCI扩展这样的更高级的类型系统中允许上述内容,Y
仍然难以输入。
因此,考虑到递归的可能性,我们可以定义并使用fix
组合器
fix f = f (fix f)
fix :: (a -> a) -> a
答案 1 :(得分:2)
键入应该禁止自我应用,不应该找到(t t)
的类型。如果可能,那么t
会有A -> B
类型,我们会A = A -> B
。由于自我应用是Y组合器的一部分,它也不可能给它一个类型。
不幸的是,许多Prolog系统允许A = A -> B
的解决方案。这种情况发生在许多方面,要么Prolog系统允许循环术语,那么统一将成功并且甚至可以进一步处理所得到的绑定。或者Prolog系统不允许循环术语,那么它取决于它是否实现了发生检查。如果发生检查,则统一将不会成功。如果发生检查已关闭,则统一可能会成功,但无法进一步处理生成的绑定,最有可能导致打印或进一步统一中的堆栈溢出。
所以我想这个类型的循环统一在使用的Prolog系统的给定代码中发生,并且它被忽视。
解决问题的一种方法是通过显式调用unify_with_occurs_check / 2来启用发生检查或替换代码中的任何发生的统一。
最好的问候
P.S。:以下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)