2 个版本
使用旧 Rust 2015
0.2.4 | 2023 年 5 月 19 日 |
---|---|
0.2.1 | 2023 年 5 月 18 日 |
#328 在 并发
每月 26 次下载
150KB
945 行
交互演算
交互演算(IC)是一种通过“完善”仿射 Lambda 演算获得的最小编程语言和计算模型,其方式与 Lamping 的最优归约算法完美匹配。它也可以被视为 对称交互结合子 的文本语法:两种观点是等价的。作为一个计算模型,IC 具有令人信服的特征
-
它具有高级函数,就像 Lambda 演算一样。
-
它有一个定义良好的成本模型,就像图灵机一样。
-
它是固有的并发,使其易于大规模并行。
-
它是完全线性的,使其无垃圾回收。
此仓库包含 Rust 参考实现。还可以在此处查看 Kind 形式化 here。
用法
1. 安装
git clone https://github.com/victortaelin/interaction_calculus
cd interaction_calculus
cargo install --path .
2. 创建一个 'main.ic' 文件
def id = λx x
def c2 = λf λx (dup #b f0 f1 = f; (f0 (f1 x)))
(c2 id)
3. 运行它
ic main.ic
查看 example.ic 以获取更大的示例。
语言
交互演算项由以下语法定义
term ::=
| λx term -- abstraction
| (term term) -- application
| {term term}#N -- superposition
| dup #N {p q} = term; term -- duplication
| x -- variable
其中变量具有全局作用域(可以在绑定大括号外出现)。
IC 有 4 条原始归约规则
((λx f) a)
---------- lambda application
x <- a
f
({u v}#i a)
---------------- superposition application
dup #i x0 x1 = a
{(u x0) (v x1)}#i
dup #i p q = λx f
body
----------------- lambda duplication
p <- λx0 r
q <- λx1 s
x <- {x0 x1}#i
dup #i r s = f
body
dup #i p q = {r s}#j
body
-------------------- superposition duplication
if #i == #j:
a <- fst
b <- snd
cont
else:
a <- {a0 a1}#j
b <- {b0 b1}#j
dup #i a0 a1 = fst;
dup #i b0 b1 = snd;
cont
其中,a <- b
表示全局、线性替换 a
为 b
。可以通过简单的数组写入在 O(1)
内完成,这反过来又使得所有上述规则都在 O(1)
内。
就这么多!
为什么?
考虑具有对的传统 Lambda 演算,它有两个计算规则
-
Lambda 应用:
(λx body) arg
-
成对投影:
let {a b} = {fst snd} in cont
当将Lambda演算编译到交互组合子时
-
lams
和apps
可以表示为构造节点(γ) -
pars
和lets
可以表示为复制节点(δ)
因此,lambda应用和成对投影仅仅是湮灭
Lambda Application Pair Projection
(λx body) arg let {a b} = {fst snd} in cont
---------------- -----------------------------
x <- arg a <- fst
body b <- snd
cont
ret arg ret arg a b a b
| | | | | | | |
|___| | | |___| | |
app \ / \ / let \#/ \ /
| ==> \/ | ==> \/
| /\ | /\
lam /_\ / \ pair /#\ / \
| | | | | | | |
| | | | | | | |
x body x body fst snd fst snd
"The application of a lambda "The projection of a pair just
substitutes the lambda's var substitutes the projected vars
by the application's arg, and by each element of the pair, and
returns the lambda body." returns the continuation."
但湮灭只发生在相同节点交互时。在交互网上,不同节点可以交互,这会触发另一个规则,即交换规则。该规则可以视为处理以下表达式
-
Lambda投影:
let {a b} = (λx body) in cont
-
成对应用:
({fst snd} arg)
但是,我们如何“投影”一个lambda或“应用”一个pair?在Lambda演算中,这些情况是未定义的并且会陷入停滞,应该是类型错误。然而,通过从交互组合子的角度解释交换规则的效果,我们可以为这些lambda表达式提出一种合理的归约
Lambda Application Pair Application
let {a b} = (λx body) in cont ({fst snd} arg)
------------------------------ ---------------
a <- (λx0 b0) let {x0 x1} = arg in
b <- (λx1 b1) {(fst x0) (snd x1)}
x <- {x0 x1}
let {b0 b1} = body in
cont
ret arg ret arg ret arg ret arg
| | | | | | | |
|___| | | |___| | |
let \#/ /_\ /_\ app \ / /#\ /#\
| ==> | \/ | | ==> | \/ |
| |_ /\ _| | |_ /\ _|
lam /_\ \#/ \#/ pair /#\ \ / \ /
| | | | | | | |
| | | | | | | |
x body x body var body var body
"The projection of a lambda "The application of a pair is a pair
substitutes the projected vars of the first element and the second
by a copies of the lambda that element applied to projections of the
return its projected body, with application argument."
the bound variable substituted
by the new lambda vars paired."
这,从某种意义上说,完成了lambda演算;也就是说,以前“停滞”的表达式现在有了有意义的计算。该系统按现在的写法是图灵完备的,然而,它非常有限,因为它不能复制pair,也不能复制复制的lambda。不过,有一种简单的方法可以极大地提高其表达能力:通过给lets加上标签,并将成对投影规则升级为
let #i{a,b} = #j{fst,snd} in cont
---------------------------------
if #i == #j:
a <- fst
b <- snd
cont
else:
a <- #j{a0,a1}
b <- #j{b0,b1}
let #i{a0,a1} = fst in
let #i{b0,b1} = snd in
cont
也就是说,它可能对应于交互组合子的湮灭或交换,这取决于标签#i
和#j
的值。这使得IC能够复制pair,复制复制的lambda,计算嵌套循环,执行指数运算的Church编码,表达任意递归函数,如Y组合子等。换句话说,通过这种简单的扩展,IC变得非常强大和表达力强,为我们提供了
-
一个新的计算模型,它与lambda演算类似,但可以最优归约。
-
一个通用、高阶的“核心语言”,它比lambda演算更轻便、更快。
-
交互组合子的项视图,使推理它们的图更容易。
话虽如此,请记住,IC与Lambda演算不等价。它是一个不同的模型。有一些λ项是IC无法计算的,反之亦然。例如,Lambda演算可以执行church-nats的自乘方,如λx (x x),这在IC上是不可能的。然而,在IC上,我们可以有call/cc,直接O(1)队列和完全线性的HOAS,这在Lambda演算上是不可能的。
最后,请注意,为了区分IC的“pairs”和“lets”与它们的λ-Calculus对应物,后者表现不同,我们分别称它们为“sups”和“dups”。
示例
Lambda应用和超位置投影(与pair投影相同)。
λu λv dup {a b} = {(λx x) (λy y)}; {(a u) (b v)}
------------------------------------------------ superposition-projection
λu λv {((λx x) u) ((λy y) v)}
----------------------------- lambda-application
λu λv {((λx x) u) v}
-------------------- lambda-application
λu λv {u v}
使用lambda投影复制一个函数。
dup {a b} = λx λy λz y; {a b}
----------------------------- lambda-projection
dup {a b} = λy λz y; {(λx0 a) (λx1 b)}
-------------------------------------- lambda-projection
dup {a b} = λz {y0 y1}; {(λx0 λy0 a) (λx1 λy1 b)}
------------------------------------------------- lambda-projection
dup {a b} = {y0 y1}; {(λx0 λy0 λz0 a) (λx1 λy1 λz1 b)}
------------------------------------------------------ superposition-projection
{(λx0 λy0 λz0 y0) (λx1 λy1 λz1 y1)}
演示超位置应用(不是Lambda演算的一部分)
{{(λx x) (λy y)} (λt t)}
------------------------ superposition-application
dup {a0 a1} = λt t; {((λx x) a0) ((λy y) a1)}
--------------------------------------------- lambda-projection
dup {a0 a1} = {t0 t1}; {((λx x) (λt0 a0)) ((λy y) (λt1 a1))}
------------------------------------------------------------ superposition-projection
{((λx x) (λt0 t0)) ((λy y) (λt1 t1))}
------------------------------------- lambda-application
{((λx x) (λt0 t0)) (λt1 t1)}
---------------------------- lambda-application
{(λt0 t0) (λt1 t1)}
示例3:2 + 3。
这相当于
data Nat = S Nat | Z
add : Nat -> Nat -> Nat
add (S n) m = S (add n m)
add Z m = m
main : Nat
main = add (S (S (S Z))) (S (S Z))
示例4:将not应用8次到True上。
高阶虚拟机(HVM)
《高阶虚拟机(HVM)》是IC的高性能实用实现。去看看吧!
依赖项
~2MB
~31K SLoC