In questo tutorial scriveremo alcune definizioni Lean sui rettangoli, dimostreremo un fatto che le riguarda, ne genereremo un pacchetto Swift con lungo e lo useremo. Il progetto Lean è lo stesso dei tutorial per Go, Python, TypeScript e C.
Prima di iniziare
Servono:
- Xcode o una toolchain Swift 5.9 su un Mac
- elan, il gestore delle toolchain di Lean
- il comando
lungo
elan toolchain install leanprover/lean4:v4.34.1
brew install machinefabric/tap/lungo # apt, dnf, Windows, cargo: vedi il riferimento del comando lungo
Scrivi il progetto Lean
Crea una directory con un progetto Lake in lean/:
mkdir shapes && cd shapes
mkdir lean
echo 'leanprover/lean4:v4.34.1' > lean/lean-toolchain
lean/lakefile.toml dichiara una libreria il cui modulo radice Lake compila per impostazione
predefinita:
name = "geometry"
version = "0.1.0"
defaultTargets = ["Geometry"]
[[lean_lib]]
name = "Geometry"
lean/Geometry.lean contiene le definizioni e la dimostrazione:
namespace Geometry
structure Rect where
width : Nat
height : Nat
deriving Repr
def area (r : Rect) : Nat := r.width * r.height
def scale (k : Nat) (r : Rect) : Rect :=
{ width := k * r.width, height := k * r.height }
/-- Scaling by `k` multiplies the area by `k * k`. -/
theorem area_scale (k : Nat) (r : Rect) : area (scale k r) = k * k * area r := by
simp only [area, scale]
exact Nat.mul_mul_mul_comm k r.width k r.height
/-- The rectangle with the largest area, if any. -/
def largest (rs : List Rect) : Option Rect :=
rs.foldl (fun best r => match best with
| some b => if area r > area b then some r else some b
| none => some r) none
end Geometry
Crea una volta il manifest di Lake (fa parte del progetto):
(cd lean && lake update)
Genera il pacchetto
lungo.toml indica il progetto Lake e dove va il pacchetto Swift:
project = "lean"
[swift]
out = "geometry-swift"
lungo generate
La prima esecuzione compila il progetto Lean, e quindi controlla la dimostrazione: cambia
k * k in k nel teorema e lungo generate fallisce con l’errore di Lean. geometry-swift è
un pacchetto Swift con il prodotto Geometry; aggiungi .lungo/ (lo spazio di lavoro di
lungo) a .gitignore.
Chiamalo da Swift
Un pacchetto da riga di comando accanto a esso, Package.swift:
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "Shapes",
platforms: [.macOS("12.0")],
dependencies: [.package(path: "geometry-swift")],
targets: [
.executableTarget(name: "Shapes", dependencies: [.product(name: "Geometry", package: "geometry-swift")])
]
)
Sources/Shapes/main.swift:
import Geometry
let r = Rect(width: 3, height: 4)
print("area:", try area(r))
let bigger = try scale(10, r)
print("scaled:", bigger.width, "x", bigger.height)
if let best = try largest([r, bigger]) {
print("largest:", best.width, "x", best.height)
}
$ swift run
area: 12
scaled: 30 x 40
largest: 30 x 40
La structure è diventata una struct Swift, Nat un LungoNat (con letterali interi),
Option un opzionale, e ogni funzione è throws. Il codice Objective-C usa lo stesso
pacchetto tramite la sua API C: @import GeometryProgram;.
Che cosa abbiamo fatto
Abbiamo generato un pacchetto Swift da un progetto Lake di cui Lean ha controllato le
dimostrazioni; esegue il codice compilato di Lean sul runtime di lungo, che lungo-swift
fornisce come XCFramework. Prossimi passi:
- Pacchetti generati: ogni tipo Lean in Swift
- Come chiamare codice dell’host da Lean
- Come distribuire i pacchetti generati