Ян Малаховски. Введение в agda
DESCRIPTION
С точки зрения программиста Agda представляет собой язык с зависимой системой типов и Haskellеподобным синтаксисом. С точки зрения математика — это система проверки доказательств, отдающая предпочтение прямому манипулированию proof-термами, а не тактикам. Доклад рассматривает основные особенности и идиомы системы Agda на примерах, широко используемых в дискретной математике. От слушателя ожидаются базовые знания функционального программирования и дискретной математики на уровне первого курса университета, хотя бы поверхностное знакомство с зависимыми типами.TRANSCRIPT
. . . . . .
Introduction to Agda (for Haskellers)
Jan Malakhovski
@oxij at twier
July, 12 2012
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 1 / 32
. . . . . .
.
......Здесь нет ничего интересного.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 2 / 32
. . . . . .
Tools.Agda and agda-mode for Emacs..
......
Установите emacs.
Установите всё с подстрокой “agda” из пакетного менеджера илиcabal.
Запустите agda-mode setup.
Запустите emacs. C-x C-f Test.agda <RET> M-x agda2-mode.
Интерактивное конструирование программ доступно только вemacs, vim не покатит.
Комбинации клавиш на странице в Agda Wiki. Самые главные:C-c C-l, C-c C-r, C-c C-,, C-c C-c.
.Standart Library..
......
http://www.cse.chalmers.se/~nad/repos/lib/
Огромная. Полгода для того чтобы начать её понимать.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 3 / 32
. . . . . .
Syntax.Lexing..
......
Мегапростой лексер делит строку по: “ ”, “( )” и “ ”. Допустимылюбые символы UNICODE в именах.
Большие буквы ничего не значат.
forall ⇔ ∀ (\all в agda2-mode)-> ⇔ → (\to в agda2-mode)
.Parsing..
......
MixFix. “_” в именах функций обозначают позиции аргументов.
→ — не типовая стрелка в обычном понимании, иногда можноопускать.
.Compilation........is top-down. Это важно.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 4 / 32
. . . . . .
Haskell vs. Agda
-- Haskell
module FProg120712 wheredata Tree a = Leaf
| Node a (Tree a) (Tree a)
data Either a b = Le a| Right b
lemost : Tree a -> Either () alemost Leaf = Le ()lemost (Node a Leaf _) = Right alemost (Node _ l _) = lemost l
-- Agda (*)
module FProg120712 wheredata Tree A : Set where
Leaf : Tree ANode : A → Tree A
→ Tree A → Tree A
data _or_ A B : Set wherele : A → A or Bright : B → A or B
record ⊤ : Set wherelemost : ∀ {A} → Tree A
→ ⊤ or Alemost Leaf = le _lemost (Node a Leaf _) = right alemost (Node _ l _) = lemost l
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 5 / 32
. . . . . .
Haskell vs. Agda
-- Agda (*)
module FProg120712 wheredata Tree A : Set where
Leaf : Tree ANode : A → Tree A
→ Tree A → Tree A
data _or_ A B : Set wherele : A → A or Bright : B → A or B
record ⊤ : Set wherelemost : ∀ {A} → Tree A
→ ⊤ or Alemost Leaf = le _lemost (Node a Leaf _) = right alemost (Node _ l _) = lemost l
-- Agda (**)
module FProg120712 wheredata Tree (A : Set) : Set where
Leaf : Tree ANode : (_ : A) → (_ : Tree A)
→ (_ : Tree A) → Tree A
data _or_ (A B : Set) : Set wherele : (_ : A) → A or Bright : (_ : B) → A or B
record ⊤ : Set whereconstructor -- Faked name
lemost : {A : _} → Tree A→ ⊤ or A
lemost {_} Leaf = le _lemost {_} (Node a Leaf _) = right alemost {_} (Node _ l _) = lemost l
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 5 / 32
. . . . . .
Unsugaring datatype syntax
data _or_ (A : Set) (B : Set) : Set wherele : (_ : A) → A or′ Bright : (_ : B) → A or′ B
data _or_ : (_ : Set) → Set → Set wherele : ∀ {A B} → A → A or′ Bright : ∀ {A B} → B → A or′ B
data _or_ : (_ : Set) → (_ : Set) → Set wherele : {A B : _} (_ : A) → A or′ Bright : {A : _} {B : _} → B → A or′ B
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 6 / 32
. . . . . .
Sets (types, kinds, sorts, . . . )
.Relation..
......
x : Type : Set₀ : Set₁ : Set₂ : Set₃ : …Non-UNICODE:
x : Type : Set0 : Set1 : Set2 : Set3 : …
.Syntax..
......“Set” — алиас для “Set₀” (“*” в Haskell).
.Properties..
......
Not cumulative:
YES: Set : Set₁; Set → Set : Set₁; Set₁ → Set : Set₂;
NO: Set : Set₂; Set₁ → Set : Set₃.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 7 / 32
. . . . . .
Postulates, BUILTINs, universe polymorphism
data N : Set wherezero : Nsucc : N → N{-# BUILTIN NATURAL ℕ #-}{-# BUILTIN ZERO zero #-}{-# BUILTIN SUC succ #-}infix 6 _+__+_ : N → N → N0 + m = m(succ n) + m = succ (n + m)
{-# BUILTIN NATPLUS + #-}one = 0 + 1four = 2 + 2
infixl 6 ⊔postulate
Level : Setlzero : Levellsucc : Level → Level⊔ : Level → Level → Level
{-# BUILTIN LEVEL Level #-}{-# BUILTIN LEVELZERO lzero #-}{-# BUILTIN LEVELSUC lsucc #-}{-# BUILTIN LEVELMAX � #-}
id : {α : Level} {A : Set α}→ A → A
id {α} {A} a = a
Level is just a non-paernmatchable N with “maximum” operation ( ⊔ ).
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 8 / 32
. . . . . .
Well-known datatypesinfixr 5 _::_data List {α} (A : Set α) : Set α where[ ] : List A_::_ : A → List A → List A
infixr 5 _::+_data Vec {α} (A : Set α) : N → Set α where[0] : Vec A 0_::+_ : ∀ {n} → A → Vec A n → Vec A (succ n)
testList = 0 :: 1 :: 2 :: 3 :: [ ]testVec = 0 ::+ 1 ::+ 2 ::+ 3 ::+ [0]
headL : ∀ {α} {A : Set α} → List A → AheadL [ ] = { !!} -- Should be totalheadL (a :: as) = a
headV : ∀ {α} {A : Set α} {n} → Vec A (succ n) → AheadV (a ::+ as) = a
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 9 / 32
. . . . . .
Syntax sugar.Types..
......
(_ : A) → B ⇔ A → B(A : X) → (B : Y) → C ⇔ (A : X) (B : Y) → C(A : X) → (B : X) → C ⇔ (A B : X) → C
(A B : _) → C ⇔ ∀ A B → CSame for “ ”, except for some funny reason {_ : A} has no sugar.
.Datatypes..
......
data Name Parameter* : [Index → ] * SetLevel whereConstructor*
Parameters are universally quantified Indexes.
Parameters are implicit arguments for datatype Constructors.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 10 / 32
. . . . . .
Syntax unsugar exercises
◦ : ∀ {α β γ} {A : Set α}{B : A → Set β}{C : {x : A} → B x → Set γ}→ (∀ {x} (y : B x) → C y)→ (g : (x : A) → B x)→ (x : A) → C (g x)
f ◦ g = λ x → f (g x)
infixr 0 _$__$_ : ∀ {α β} {A : Set α}{B : A → Set β}→ (∀ x → B x)→ (∀ x → B x)
f $ x = f x
_o_ : {α β γ : Level} {A : Set α} {B : A → Set β}{C : {x : A} → B x → Set γ}→ (f : {x : A} → (y : B x) → C {x} y)→ (g : (x : A) → B x)→ (x : A) → C {x} (g x)
f o g = λ x → f {x} (g x)
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 11 / 32
. . . . . .
Type theoretic datatypes
.Negation..
......
data ⊥ : Set where⊥-elim : ∀ {α} {A : Set α} → ⊥ → A⊥-elim ()
¬ : ∀ {α} → Set α → Set α¬ P = P → ⊥
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 12 / 32
. . . . . .
.Sum and product..
......
data ∨ {α β} (A : Set α) (B : Set β) : Set (α ⊔ β) whereinj₁ : A → A ∨ Binj₂ : B → A ∨ B
record Σ {α β} (A : Set α) (B : A → Set β) : Set (α ⊔ β) whereconstructor _, _field
proj1 : Aproj2 : B proj1
open Σ public∧ : ∀ {α β} (A : Set α) (B : Set β) → Set (α ⊔ β)
A ∧ B = Σ A (λ _ → B)
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 13 / 32
. . . . . .
Properties for natural numbers
_≠0 : N → Set0 ≠0 = ⊥_ ≠0 = ⊤data _<_ : N → N → Set where
0 <∀ : ∀ {n} → 0 < succ ns<s : ∀ {n m} → n < m → succ n < succ m
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 14 / 32
. . . . . .
Examples
test≠0 : Σ N (λ n → n ≠0)test≠0 = 1,
syntax Σ A (λ x → B) = ∃ [x ∶ A ] B
test¬≠0 : ∃ [n ∶ N ] (¬ ◦ _≠0) ntest¬≠0 = 0, (λ z → z)
test¬<0 : ¬ (∃ [n ∶ N ] (n < 0))test¬<0 (n, n<0) = sub n n<0 where
sub : ∀ n → n < 0 → ⊥sub zero ()sub (succ n) ()
nzplus : (n : N) → {nz : n ≠0} → N → Nnzplus zero {()} mnzplus (succ n) m = n + m
testnzplus = nzplus 1 3testnzplus′ = nzplus 0 3 -- Unresolved constraint
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 15 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 16 / 32
. . . . . .
Type-theoretic properties
.Martin-Lof (propositional) equality..
......
infix 4 _≡_data _≡_ {α} {A : Set α} (a : A) : A → Set α where
refl : a ≡ a
z=z : 0 ≡ 0z=z = refl {_} {N} {0}cong : ∀ {α β} {A : Set α} {B : Set β}(f : A → B) {x y}→ x ≡ y → f x ≡ f y
cong f refl = refl
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 17 / 32
. . . . . .
Arithmetic examples
z+n=n : ∀ n → 0 + n ≡ nz+n=n n = refl
n+z=n : ∀ n → n + 0 ≡ nn+z=n zero = refln+z=n (succ n) = cong succ $ n+z=n n
+-assoc : ∀ n m l → n + (m + l) ≡ (n + m) + l+-assoc zero m l = refl+-assoc (succ n) m l = cong succ $ +-assoc n m l
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 18 / 32
. . . . . .
Lists
length : ∀ {α} {A : Set α} → List A → Nlength [ ] = 0length (_ :: as) = 1 + length as
elementAt : ∀ {α} {A : Set α} n → (l : List A) → n < length l → AelementAt zero [ ] ()elementAt zero (a :: _) 0 <∀ = aelementAt (succ n) [ ] ()elementAt (succ n) (_ :: as) (s<s s) = elementAt n as s
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 19 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 20 / 32
. . . . . .
Interruption
_≤_ : N → N → Setn ⩽ m = (n ≡ m) ∨ (n < m)
unsucc : ∀ {n m} → succ n ≡ succ m → n ≡ munsucc refl = refl
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 21 / 32
. . . . . .
Lists again
take : ∀ {α} {A : Set α} n → (l : List A) → n ⩽ length l → List Atake zero _ _ = [ ]take (succ n) [ ] (inj₁ ())take (succ n) [ ] (inj₂ ())take (succ n) (a :: as) (inj₁ eq) = a :: take n as (inj₁ $ unsucc eq)take (succ n) (a :: as) (inj₂ (s<s n<m)) = a :: take n as (inj₂ n<m)
takeV : ∀ {α} {A : Set α} {m} n → (l : Vec A m) → n ⩽ m→ Vec A n
takeV zero _ _ = [0]takeV (succ n) [0] (inj₁ ())takeV (succ n) [0] (inj₂ ())takeV (succ n) (a ::+ as) (inj₁ eq) = a ::+ takeV n as (inj₁ $ unsucc eq)takeV (succ n) (a ::+ as) (inj₂ (s<s n<m)) = a ::+ takeV n as (inj₂ n<m)
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 22 / 32
. . . . . .
Listsdata Bool : Set where
true false : Bool
isTrue : Bool → SetisTrue true = ⊤isTrue false = ⊥_≤?_ : N → N → Boolzero ≤? _ = truesucc _ ≤? zero = falsesucc n ≤? succ m = n ≤? m
unsuccIt : ∀ n m → isTrue (succ n ≤? succ m) → isTrue (n ≤? m)unsuccIt n m = id
take′ : ∀ {α} {A : Set α} n → (l : List A)→ {_ : isTrue (n ≤? length l)} → List A
take′ zero _ = [ ]take′ (succ n) [ ] {()}take′ (succ n) (a :: as) { it} = a :: take′ n as { it}Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 23 / 32
. . . . . .
∈ for Listsdata _∈_ {α} {A : Set α} : A → List A → Set α where
Z : ∀ {a as} → a ∈ (a :: as)S : ∀ {a b as} (n : a ∈ as) → a ∈ (b :: as)
⊆ : ∀ {α} {A : Set α} → List A → List A → Set αas ⊆ bs = ∀ {a} → a ∈ as → a ∈ bs
take ⊆ : ∀ {α} {A : Set α} n (l : List A)→ (n<ll : n ⩽ length l) → take n l n<ll ⊆ l
take ⊆ zero _ _ ()take ⊆ (succ n) [ ] (inj₁ ()) _take ⊆ (succ n) [ ] (inj₂ ()) _take ⊆ (succ n) (a :: as) (inj₁ eq) Z = Ztake ⊆ (succ n) (a :: as) (inj₁ eq) (S n’) =
S (take ⊆ n as (inj₁ $ unsucc eq) n’)take ⊆ (succ n) (a :: as) (inj₂ (s<s n<m)) Z = Ztake ⊆ (succ n) (a :: as) (inj₂ (s<s n<m)) (S n’) =
S (take ⊆ n as (inj₂ n<m) n’)
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 24 / 32
. . . . . .
filter : ∀ {α} {A : Set α} → (p : A → Bool)→ List A → List A
filter p [ ] = [ ]filter p (a :: as) with p a… | true = a :: (filter p as)… | false = filter p as
filter ⊆ as : ∀ {α} {A : Set α}→ (as : List A) → (p : A → Bool) → (filter p as) ⊆ as
filter ⊆ as [ ] p = λ z → zfilter ⊆ as {A = A} (a :: as) p with p a… | false = λ n → S (filter ⊆ as as p n)… | true = go where
go : {a’ : A} → a’ ∈ (a :: filter p as) → a’ ∈ (a :: as)go Z = Zgo (S n) = S (filter ⊆ as as p n)
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 25 / 32
. . . . . .
reverse
≡-sym : ∀ {α} {τ : Set α} {a b : τ} → a ≡ b → b ≡ a≡-sym refl = refl
≡-trans : ∀ {α} {τ : Set α} {a b c : τ}→ a ≡ b → b ≡ c → a ≡ c
≡-trans refl refl = refl
infixl 5 _++__++_ : ∀ {a} {A : Set a} → List A → List A → List A[ ] ++ bs = bs(a :: as) ++ bs = a :: (as ++ bs)
++-assoc : ∀ {α} {A : Set α} → (as bs cs : List A)→ (as ++ (bs ++ cs)) ≡ ((as ++ bs) ++ cs)
++-assoc [ ] bs cs = refl++-assoc (a :: as) bs cs = cong (λ ℓ → a :: ℓ) (++-assoc as bs cs)
++ [ ] : ∀ {α} {A : Set α} → (as : List A) → (as ++ [ ]) ≡ as++ [ ] [ ] = refl++ [ ] (a :: as) = cong (λ ℓ → a :: ℓ) (++ [ ] as)Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 26 / 32
. . . . . .
reverse : ∀ {a} {A : Set a} → List A → List Areverse [ ] = [ ]reverse (a :: as) = (reverse as) ++ (a :: [ ])
reverse++ : ∀ {a} {A : Set a} → (as bs : List A)→ (reverse (as ++ bs)) ≡ ((reverse bs) ++ (reverse as))
reverse++ [ ] bs = ≡-sym $ ++ [ ] (reverse bs)reverse++ (a :: as) bs = ≡-trans(cong (λ ℓ → ℓ ++ (a :: [ ])) (reverse++ as bs))(≡-sym $ ++-assoc (reverse bs) (reverse as) (a :: [ ]))
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 27 / 32
. . . . . .
Modules
open import ModuleName instead of Haskell’simport ModuleName;
Agda’s import ModuleName is import qualified ModuleName inHaskell (i.e. import, but don’t open module’s namespace);Special keywords:
▶ as — give another name;▶ using — cherry pick names;▶ hiding — hide some names;▶ renaming — cherry pick and rename names;▶ public — and add to module export list.
Nested modules are OK.
Modules can have parameters.
records are modules.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 28 / 32
. . . . . .
Environment and visibility control
module Tralala where-- (1)
module Dummy whereTweedledum : …Tweedledum = {!!}
-- (2)
Tweedledee : …Tweedledee = {!!}
-- (3)
-- (4)
open Dummy publicusing (Tweedledee)
-- (5)
∅ at (1)
Tweedledum at (2)
Tweedledum and Tweedledeeat (3)
Dummy.Tweedledum andDummy.Tweedledee at (4)
Dummy.Tweedledum,Dummy.Tweedledee andTweedledee at (5)
Tweedledee outside of themodule.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 29 / 32
. . . . . .
Заключение
Если кому-то показалось, что что-то выше проверяется в runtime,то он ошибся.
Всё проверяется статически, доказательства (как правило)стираются при компиляции.
.Main features..
......
Структурная индукция.
Семейства типов.
Зависимое сопоставление с образцом.
Lazyness is essential!
У простых алгоритмов простые доказательства.
I.e. полезно даже если вы не очень математик.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 30 / 32
. . . . . .
Не рассмотрены
Всё самое интересное.
Dot-paerns.
IO.
Reflection.
Standart Library.
Back-ends.
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 31 / 32
. . . . . .
.
...... estions?
.
......
The proof is trivial! Just biject it to a
context-freetopological space
whose elements are
computableequivalence relations
hp://theproofistrivial.com/
Jan Malakhovski (@oxij at twier) Introduction to Agda (for Haskellers) July, 12 2012 32 / 32