11 个版本

使用旧的 Rust 2015

0.1.11 2018年12月7日
0.1.10 2018年11月26日
0.1.8 2018年10月25日

#1041 in 编程语言

MIT 许可证

105KB
2K SLoC

Formality

一种通用编程语言,适用于前端应用、后端服务和智能合约。它是

  • 快速:没有垃圾回收,最优的 beta-归约和大规模并行 GPU 编译器使其非常快。

  • 安全:能够证明其自身程序数学定理的类型系统使其非常安全。

  • 简单:整个实现约为 2k 行代码,使其成为简单的标准,您可以自己实现。

定理证明 由于依赖类型,如在其他证明辅助工具中一样是可能的。由于 对称交互演算 (SIC),一种结合了图灵机和 λ-演算最佳特点的新计算模型,因此可以实现大规模并行评估。由于线性,无需垃圾回收:值超出作用域时即可简单地释放。要使用变量两次,我们只需克隆它:SIC 的 懒复制 使其几乎免费。由于不需要所有权系统,我们具有类似 Rust 的计算属性,同时具有类似 Haskell 的高级感觉。

目录

安装

要安装 Formality,首先确保您 已安装 Rust

curl -sSf https://static.rust-lang.org/rustup.sh | sh

然后通过克隆存储库来安装它

git clone https://github.com/maiavictor/formality
cd formality
cargo install

使用方法

示例用法

git clone https://github.com/maiavictor/formality
cd examples

# Interpreter evaluation
formality everything.formality.hs -e not_true 

# SIC evaluation
formality everything.formality.hs -s -f not_true 

# Type-checking
formality everything.formality.hs -t add
formality everything.formality.hs -t add-comm

示例

形式语言非常简单。其程序由两个构建块组成:归纳数据类型,用于表示数据格式;以及函数,用于表示对这些类型数据的计算。这就是你需要的一切。

简单类型

最简单的类型之一,布尔类型,可以声明为

data Bool : Type
| true    : Bool
| false   : Bool

否定函数可以声明为

let not(b : Bool) =>
    case b  -> Bool
    | true  => Bool.false
    | false => Bool.true

当我们想要检查数据类型的值时,都会使用模式匹配。

递归类型

最简单的递归类型之一,自然数,可以声明为

data Nat : Type
| succ   : (n : Nat) -> Nat
| zero   : Nat

一个将其翻倍的功能可以写成

let double(a : Nat) =>
    case a       -> Nat
    | succ(pred) => Nat.succ(Nat.succ(fold(pred)))
    | zero       => Nat.zero

由于形式语言是全总性的,递归是通过使用fold关键字来执行的,这个关键字在模式匹配的case中可用。它允许我们将相同的逻辑递归地应用到结构上更小的值。

多态类型

类型可以轻松地参数化

data Pair<A : Type, B : Type> : Type
| new : (x : A, y : B) -> Pair

声明多态函数就像将类型作为参数一样简单

let fst(A : Type, B : Type, pair : Pair<A, B>) =>
    case pair   -> A
    | new(x, y) => x

这允许你为多个具体类型重用同一个函数的实现,这是一个强大而古老的技巧,某些“现代系统语言”竟然无法正确实现。

依赖类型

形式语言允许类型不仅由其他静态类型参数化,还可以由运行时值参数化:我们称之为“索引”。经典的Vector类型,其长度在编译时是符号已知的,可以声明为

data Vect<A : Type> : (n : Nat) -> Type
| cons : (n : Nat, x : A, xs : Vect(n)) -> Vect(Nat.succ(n))
| nil  : Vect(Nat.zero)

当我们对那些类型进行模式匹配时,我们可以指定一个依赖于索引的返回类型

let tail(A : Type, n : Nat, vect : Vect<A>(Nat.succ(n))) =>
    case vect        -> (n) => Vect<A>(pred(n))
    | cons(n, x, xs) => xs
    | nil            => Vect<A>.nil

这允许我们编写强大的类型安全函数,例如一个不能溢出的向量的索引函数。我们还可以使用self关键字来引用匹配的结构本身,允许我们表达数学归纳(见示例)。

定理证明

这些功能允许形式语言将定理表达为类型。例如,数学上的等价可以定义为

data Eq<A : Type> : (x : A, y : A) -> Type
| refl : (x : A) -> Eq(x, x)

而证明a == b意味着b == a的证明只是

let sym(A : Type, a : A, b : A, e : Eq<A>(a, b)) =>
    case e    -> (a, b) => Eq<A>(b, a)
    | refl(x) => Eq<A>.refl(x)

有了这么高的表现力,形式语言类型可以被视为“规范语言”。例如,我们可以写出“排序列表的类型”、“大于10的质数的类型”,甚至“不能被耗尽的智能合约的类型”。

最优评估

以下形式语言程序

id(1000000000(List<Bool>, map(Bool, Bool, not), list))

翻转一个100位长列表中的每个比特,一亿次。它在0.03s内打印正确的输出。你可以将其增加到超过宇宙中的星星数量,它仍然会立即输出正确的结果。不,你的计算机并没有进行那么多操作:这是因为形式语言被编译为SIC,这是一种函数程序的最优评估器。这使得它可以利用其他语言无法比拟的疯狂运行时优化,使其通常比几十年的编译器(如GHC)还要快。

更多示例

有关更多示例,请查看/examples目录。

警告

形式语言仍处于实验阶段。有些功能缺失,代码可能存在错误。请勿将其用于火箭引擎。有关更多信息,请参阅此线程

依赖项

~1MB