Compiler construction 非类型Lambda演算的函数语言

Compiler construction 非类型Lambda演算的函数语言,compiler-construction,functional-programming,interpreter,lambda-calculus,untyped-variables,Compiler Construction,Functional Programming,Interpreter,Lambda Calculus,Untyped Variables,是否有用于非类型化lambda演算的解释器(或编译器)?(根据它是可能的。)我认识到它作为一种编程语言没有什么用处,特别是如果大部分语言(如数字和布尔运算符)都是(由用户或库)在语言本身中实现的。然而,我仍然认为这将是一个有趣的工具,有助于学习和探索微积分。对于这一点,解释器比编译器更可取,尽管两者都可以工作。有人知道这样的程序吗?使用一些技巧,这几乎可以在任何函数式语言中实现。至少我在Haskell和OCaml中看到过类似的情况。然而,有时您必须绕过类型系统的限制。通常,通过将“非类型化”特性

是否有用于非类型化lambda演算的解释器(或编译器)?(根据它是可能的。)我认识到它作为一种编程语言没有什么用处,特别是如果大部分语言(如数字和布尔运算符)都是(由用户或库)在语言本身中实现的。然而,我仍然认为这将是一个有趣的工具,有助于学习和探索微积分。对于这一点,解释器比编译器更可取,尽管两者都可以工作。有人知道这样的程序吗?

使用一些技巧,这几乎可以在任何函数式语言中实现。至少我在Haskell和OCaml中看到过类似的情况。然而,有时您必须绕过类型系统的限制。通常,通过将“非类型化”特性实现为一个单元类型系统来获得它。所以每个lambda函数都有

type lambda = lambda -> lambda
例如,在默认设置中,OCaml将不允许这种递归类型,但可以通过定义以下内容来避免这种情况:

type lambda = L of lambda -> lambda

本杰明·皮尔斯(Benjamin Pierce)在他的教科书中提供了一系列的和λ-微积分。它们是用OCaml编写的,并包含示例定义。然而,为简单的λ-运算编写解释器或编译器并不困难。

我是函数式编程课程的助教。出于教学目的,我们在网上看到这是一个探索微积分的有趣而有用的工具。如果你想使用SML,它们也有可用的源代码。

我在今年早些时候写了一个

是用Python编写的。这看起来很不成熟,但这是实现一个Python的有趣的开始。它取决于模块
ply

是C++的另一种(很有意思)-非常有趣。 如果您的主要目的是在学习lambda微积分(例如,尝试为自己推导算术运算)和特定的Church数字和布尔值时实现一些基本的自动化,那么一个简单但易于实现的解决方案是将自己限制在Python的一小部分,您可以在其中定义自己的数字和运算符,并通过将其转换为常规Python类型的函数对其进行检查。对教堂数字执行此操作的函数:

lambda churchnum: churchnum(lambda x: x+1)(0)
还有一个是教会的布尔人:

lambda churchbool: churchbool(True)(False)

您可以使用任何具有lambda抽象的非类型化语言。例如Python或JavaScript。有两个主要缺点:

  • 这些语言没有延迟计算。这意味着并非所有lambda项都会收敛,即使它们具有标准形式。您必须考虑到这一点,并相应地修改任务
  • 您不会看到正常形式的lambda项的结果。您必须知道从结果中期望得到什么,并使用语言将其评估为可以显示的内容
  • 了解了这一点,让我们以Python为例: 首先,我们创建助手函数,以便在数字和教堂数字之间进行转换:

    lambda churchnum: churchnum(lambda x: x+1)(0)
    
    #从整数构造数字
    def int2church(n):
    def重复(f、m、x):
    如果(m==0):返回x
    否则:返回f(重复(f,m-1,x))
    返回λf:(λx:重复(f,n,x))
    def丘吉尔(l):
    返回l(λx:x+1)(0)
    
    现在我们可以定义数字的标准操作:

    lambda churchnum: churchnum(lambda x: x+1)(0)
    
    zero=int2church(0)
    一=int2church(1)
    pred=lambda n:lambda f:lambda x:n(lambda g:lambda h:h(g(f))(lambda u:x)(lambda u:u)
    mul=lambda m:lambda n:(lambda f:m(n(f)))
    expn=lambda n:lambda m:m(n)
    tetra=lambda n:lambda m:m(expn(n))(一)
    
    并计算例如43:

    expn=lambda n:(lambda m:m(n))
    a=int2church(4)
    b=int2church(3)
    打印内容(扩展(a)(b))
    
    或:

    a=int2church(5)
    b=int2church(2)
    打印丘吉尔(tetra(a)(b))
    
    为了能够表达更有趣的东西,我们可以定义Y组合符:

    y=lambda f:(lambda x:f(lambda v:x(x)(v))(lambda x:f(lambda v:x(x)(v)))
    
    并计算例如阶乘:

    true=lambda x:(lambda y:x)
    false=λx:(λy:y)
    iszero=lambda n:n(lambda x:false)(true)
    事实=y(λr:λn:is0(n)(一)(mul(n)(λx:r(pred(n))(x)))
    打印church2int(事实(int2church(6)))
    
    请注意,Y combinator必须适用于使用的严格求值以及阶乘函数,以避免由于严格求值而产生的无限递归。

    我创建了一个基于lambda演算的语言,我调用该语言来学习lambda演算的工作原理。对于希望以交互方式以最小的符号复杂性学习和体验计算机科学的一些基本原理的人来说,它可能很有用

    是一个基于Lambda演算功能的编程环境,但具有简化的表示法。允许定义、应用和减少功能抽象。符号和语法是最小的,但足以使基础概念易于理解

    底层编译器是用Python编写的,并将抽象编译成函数,当相互应用时,这些函数会自动简化为正常形式(如果可能)。这意味着,如果定义S、K和I组合函数,然后将它们应用为S K,则返回的函数将是I函数,而不仅仅是一个行为类似于I的函数,这意味着以下内容将成立:

    >>>S(K)(K) is I
    True
    

    我的是JavaScript,它包括一个编译器(转换成JavaScript函数)、一个计算器(alpha/beta/eta转换)和一个包含13条指令的虚拟机。VM实现中存在一些已知的错误,但编译器和计算器似乎工作正常。这是一个高质量的答案+1利息: