Lambda微积分发生器


10

我不知道在哪里可以问这个问题,我希望这是一个好地方。

我只是想知道是否有可能制造一个lambda演算生成器;本质上,在给定无限时间的情况下,一个循环会产生所有可能的lambda微积分函数。(如字符串形式)。

由于Lambda演算非常简单,因此只有少数几个元素可以表达(我认为不是很有用),但从最简单的组合开始就可以生成所有可能的Lambda表达式。微积分功能。

当然,我对lambda微积分几乎一无所知,所以我不知道这是否真的可能。

是吗?如果是这样,它是否像我所设想的那样简单明了,或者从技术上讲是可能的,但是如此困难以至于实际上是不可能的?

PS。我不是在谈论减少beta的函数,而是在谈论每个lambda演算函数的每个有效符号。

Answers:


19

当然,这是一个标准的编码练习。

首先,让任何双射可计算函数,称为配对函数。标准选择是p:N2N

p(n,m)=(n+m)(n+m+1)2+n

可以证明这是一个双射,因此给定任何自然,我们可以计算,从而。n m p n m = kkn,mp(n,m)=k

要枚举lambda项,请修复变量名称的所有枚举:。x0,x1,x2,

然后,对于每个自然数,按如下所示递归定义:b d 一个ilambda(i)

  • 如果是偶数,令并返回变量j = / 2 x jij=i/2xj
  • 如果是奇数,则让j = i 1 / 2ij=(i1)/2
    • 如果是偶数,令并找到使得;计算 ; 退货申请书k = j / 2 n m p n m = k N = l a m b d a n M = l a m b d a m N M jk=j/2n,mp(n,m)=kN=lambda(n),M=lambda(m)(NM)
    • 如果是奇数,则令并找到使得;计算 ; 返回抽象ķ = Ĵ - 1 / 2 Ñ p Ñ = ķ 中号= b d λ X Ñ中号jk=(j1)/2n,mp(n,m)=kM=lambda(m)(λxn. M)

该程序通过以下涉及所有lambda项 “代数”双射来证明是正确的:Λ

ΛN+(Λ2+N×Λ)

它被理解为“ lambda项,在语法上是1)变量(表示为自然数),2)应用程序(由两个lambda项构成)和3)抽象(一对变量/自然+ lambda项)的不相交并集)”。

鉴于此,我们递归地应用可计算的双射()和(标准偶/奇数)来获得上述算法。 p Ñ + Ñ ÑN2NpN+NN

此过程是通用的,几乎可用于通过上下文无关语法生成的任何语言,该语言将提供与上述类似的同构功能。


哇,谢谢,您有可能代表这是伪代码吗?我肯定会更好,因为我没有CS学位。
合法堆栈

3
@LegitStack好吧,以上是伪代码:)您可以定义一个递归函数然后使用。唯一不平凡的步骤是找到使得:可以通过尝试对所有与配对(也存在更​​快的算法)lambda(n)if n%2==0 ...n,mp(n,m)=kn,mn,mk
chi

1
实际上,根据Wikipedia,可以通过找到此特定配对函数的逆函数。a=12(8k+11),b=12a(a+1),n=bk,m=an
LegionMammal978

12

是。采取枚举所有可能的ASCII字符串的方式。对于每个输出,请检查是否定义了函数的有效lambda演算语法;如果没有,请跳过它。(可以进行检查。)该方法枚举了所有的lambda演算函数。


5
基本上,通过调用打字猴子可以解决所有此类问题……
xuq01 '18

5
或者,您可以直接枚举lambda微积分项。比随机字符串要快得多,因为每个输出都是格式正确的术语。这就像用莎士比亚戏剧生成器代替打字猴子。
Dan D.

11

如前所述,这只是从上下文无关的语言中枚举术语,因此绝对可行。但是,它背后还有更多有趣的数学,进入了分析组合学领域。

文章在二元Lambda演算计数和生成项包含对枚举问题的处理,以及更多其他内容。为了简化起见,他们使用了一种称为二元lambda calulus的东西,它只是使用De Bruijn索引对lambda项进行的编码,因此您不必命名变量。

该论文还包含实现其生成算法的具体Haskell代码。这绝对是有效的可能。

我碰巧用Julia 写了他们的方法的实现


7

当然。我们可以根据lambda术语的定义直接生成它们。

在Haskell中,我们首先定义数据类型,

data LC a  =  Var  a                -- Constructor <type> <type> ...
           |  App (LC a) (LC a)     --
           |  Lam  a     (LC a)     --  ... alternatives ...

instance Show a => Show (LC a)      -- `LC a` is in Show if `a` is in Show, and
  where
    show (Var i)    =  [c | c <- show i, c /= '\'']
    show (App m n)  =  "("  ++ show m       ++ " " ++ show n ++ ")"
    show (Lam v b)  =  "(^" ++ show (Var v) ++ "." ++ show b ++ ")"

然后使用Fair(er)join

lambda :: [a] -> [LC a]
lambda vars  =  terms 
  where
  terms  =  fjoin [ map Var vars ,
                    fjoin [ [App t s | t <- terms] | s <- terms ] ,
                    fjoin [ [Lam v s | v <- vars ] | s <- terms ] ]

  fjoin :: [[a]] -> [a]
  fjoin xs  =  go [] xs             -- fairer join
      where 
      go [] []  =  []
      go a  b   =  reverse (concatMap (take 1) a) ++ go 
                       (take 1 b ++ [t | (_:t) <- a]) (drop 1 b)

我们只列举它们,例如

> take 20 $ lambda "xyz"
[x,y,(x x),z,(y x),(^x.x),(x y),(^y.x),((x x) x),(^x.y),(y y),(^z.x),(x (x x)),
 (^y.y),(z x),(^x.(x x)),((x x) y),(^z.y),(y (x x)),(^y.(x x))]

> take 5 $ drop 960 $ lambda "xyz"
[(((x x) y) (z x)),(^y.(^x.((x x) (x x)))),((^x.(x x)) (^x.(x x))),(^x.((^z.x) 
 y)),((z x) ((x x) y))]

看,著名的术语离顶部不远!Ω=(λx.xx)(λx.xx)

fjoin相当于欧米茄monaddiagonal


0

我在网上遇到了一种可以从正则表达式生成示例字符串的工具:https : //www.browserling.com/tools/text-from-regex。您可以通过输入以下内容来生成许多示例lambda项:

(\( (lambda \w\. )* \w+ \))* 

当然,要获得具有任意嵌套级别的术语,您将需要使用无上下文语法,这是一种比正则表达式更具描述性的工具,用于定义语言。我还没有遇到过一种基于无上下文语法定义来生成示例语言句子的现有工具,但是没有理由无法构建这种工具。


2
该组术语不是正则表达式(如你注意)。用这种方式回答初学者的问题是有害的,因为它掩盖了一个重要的区别(即上下文无关的语法和正则表达式之间的区别)。λ
安德烈·鲍尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.