输入Y组合子

时间:2010-09-13 17:28:16

标签: prolog lambda-calculus type-theory

http://muaddibspace.blogspot.com/2008/01/type-inference-for-simply-typed-lambda.html是Prolog中简单输入的lambda演算的简明定义。

它看起来没问题,但后来他声称要为Y组合器分配一个类型...而在非常真实的意义上,将类型添加到lambda演算的整个目的是拒绝为Y组合器之类的东西分配类型

任何人都可以确切地看到他的错误或 - 更有可能 - 我的误解在哪里?

2 个答案:

答案 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)