Skip to content

Commit ae02ebb

Browse files
Merge branch 'master' into experimental
2 parents 0ef8002 + e47adf6 commit ae02ebb

File tree

259 files changed

+11636
-5081
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

259 files changed

+11636
-5081
lines changed

CHANGELOG.md

Lines changed: 770 additions & 139 deletions
Large diffs are not rendered by default.

GenerateEverything.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ unsafeModules = map modToFile
3535
, "Debug.Trace"
3636
, "Foreign.Haskell"
3737
, "Foreign.Haskell.Coerce"
38+
, "Foreign.Haskell.Either"
3839
, "Foreign.Haskell.Maybe"
3940
, "Foreign.Haskell.Pair"
4041
, "IO"

README.agda

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module README where
22

33
------------------------------------------------------------------------
4-
-- The Agda standard library, version 1.2-dev
4+
-- The Agda standard library, version 1.2
55
--
66
-- Authors: Nils Anders Danielsson, Matthew Daggitt, Guillaume Allais
77
-- with contributions from Andreas Abel, Stevan Andjelkovic,
@@ -262,6 +262,10 @@ import IO
262262
-- More documentation
263263
------------------------------------------------------------------------
264264

265+
-- Examples of how decidability is handled in the library.
266+
267+
import README.Decidability
268+
265269
-- Some examples showing how the case expression can be used.
266270

267271
import README.Case

README/Data.agda

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ import README.Data.AVL
183183

184184
import README.Data.List
185185

186+
-- Some examples showing how the Fresh list can be used.
187+
188+
import README.Data.List.Fresh
189+
186190
-- Using List's Interleaving to define a fully certified filter function.
187191

188192
import README.Data.Interleaving

README/Data/List/Fresh.agda

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Example use case for a fresh list: sorted list
5+
------------------------------------------------------------------------
6+
7+
module README.Data.List.Fresh where
8+
9+
open import Data.Nat
10+
open import Data.List.Base
11+
open import Data.List.Fresh
12+
open import Data.List.Relation.Unary.AllPairs as AllPairs using (AllPairs)
13+
open import Data.Product
14+
open import Relation.Nary using (⌊_⌋; fromWitness)
15+
16+
-- A sorted list of natural numbers can be seen as a fresh list
17+
-- where the notion of freshness is being smaller than all the
18+
-- existing entries
19+
20+
SortedList : Set
21+
SortedList = List# ℕ _<_
22+
23+
_ : SortedList
24+
_ = cons 0 (cons 1 (cons 3 (cons 10 [] _)
25+
(s≤s (s≤s (s≤s (s≤s z≤n))) , _))
26+
(s≤s (s≤s z≤n) , s≤s (s≤s z≤n) , _))
27+
(s≤s z≤n , s≤s z≤n , s≤s z≤n , _)
28+
29+
-- Clearly, writing these by hand can pretty quickly become quite cumbersome
30+
-- Luckily, if the notion of freshness we are using is decidable, we can
31+
-- make most of the proofs inferrable by using the erasure of the relation
32+
-- rather than the relation itself!
33+
34+
-- We call this new type *I*SortedList because all the proofs will be implicit.
35+
36+
ISortedList : Set
37+
ISortedList = List# ℕ ⌊ _<?_ ⌋
38+
39+
-- The same example is now much shorter. It looks pretty much like a normal list
40+
-- except that we know for sure that it is well ordered.
41+
42+
ins : ISortedList
43+
ins = 0 ∷# 1 ∷# 3 ∷# 10 ∷# []
44+
45+
-- Indeed we can extract the support list together with a proof that it
46+
-- is ordered thanks to the combined action of toList converting a fresh
47+
-- list to a pair of a list and a proof and fromWitness which "unerases"
48+
-- a proof.
49+
50+
ns : List ℕ
51+
ns = proj₁ (toList ins)
52+
53+
sorted : AllPairs _<_ ns
54+
sorted = AllPairs.map (fromWitness _<_ _<?_) (proj₂ (toList ins))
55+
56+
-- See the following module for an applied use-case of fresh lists
57+
open import README.Data.Trie.NonDependent

README/Data/Trie/NonDependent.agda

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,38 +51,57 @@ module README.Data.Trie.NonDependent where
5151
open import Level
5252
open import Data.Unit
5353
open import Data.Bool
54-
open import Data.Char as Char
55-
import Data.Char.Properties as Char
56-
open import Data.List as List using (List; []; _∷_)
57-
open import Data.List.NonEmpty as List⁺ using (List⁺; _∷_)
58-
open import Data.Maybe as Maybe
59-
open import Data.Product as Prod
60-
open import Data.String.Base as String using (String)
61-
open import Data.These as These
62-
63-
open import Function using (case_of_; _$_; _∘′_; id)
54+
open import Data.Char as Char
55+
import Data.Char.Properties as Char
56+
open import Data.List as List using (List; []; _∷_)
57+
open import Data.List.Fresh as List# using (List#; []; _∷#_)
58+
open import Data.Maybe as Maybe
59+
open import Data.Product as Prod
60+
open import Data.String as String using (String)
61+
open import Data.These as These
62+
63+
open import Function using (case_of_; _$_; _∘′_; id; _on_)
64+
open import Relation.Nary
65+
open import Relation.Binary using (Rel)
66+
open import Relation.Nullary.Negation using (¬?)
6467

6568
open import Data.Trie Char.<-strictTotalOrder-≈
6669
open import Data.AVL.Value
6770

6871
------------------------------------------------------------------------
6972
-- Generic lexer
7073

71-
module Lexer
74+
record Lexer t : Set (suc t) where
75+
field
7276
-- Our lexer is parametrised over the type of tokens
73-
{t} {Tok : Set t}
74-
-- We start with an association list between
75-
-- * keywords (as Strings)
76-
-- * keywords (as token values)
77-
(lex : List⁺ (String × Tok))
77+
Tok : Set t
78+
79+
-- Keywords are distinguished strings associated to tokens
80+
Keyword : Set t
81+
Keyword = String × Tok
82+
83+
-- Two keywords are considered distinct if the strings are not equal
84+
Distinct : Rel Keyword 0ℓ
85+
Distinct a b = ⌊ ¬? ((proj₁ a) String.≟ (proj₁ b)) ⌋
86+
87+
field
88+
89+
-- We ask users to provide us with a fresh list of keywords to guarantee
90+
-- that no two keywords share the same string representation
91+
keywords : List# Keyword Distinct
92+
7893
-- Some characters are special: they are separators, breaking a string
7994
-- into a list of tokens. Some are associated to a token value
8095
-- (e.g. parentheses) others are not (e.g. space)
81-
(breaking : Char λ b if b then Maybe Tok else Lift _ ⊤)
96+
breaking : Char λ b if b then Maybe Tok else Lift _ ⊤
97+
8298
-- Finally, strings which are not decoded as keywords are coerced
8399
-- using a function to token values.
84-
(default : String Tok)
85-
where
100+
default : String Tok
101+
102+
103+
module _ {t} (L : Lexer t) where
104+
open Lexer L
86105

87106
tokenize : String List Tok
88107
tokenize = start ∘′ String.toList where
@@ -107,7 +126,7 @@ module Lexer
107126
-- characters one by one
108127

109128
init : Keywords
110-
init = fromList $ List⁺.toList $ List⁺.map (Prod.map₁ String.toList) lex
129+
init = fromList $ List.map (Prod.map₁ String.toList) $ proj₁ $ List#.toList keywords
111130

112131
-- Kickstart the tokeniser with an empty accumulator and the initial
113132
-- trie.
@@ -148,33 +167,40 @@ module Lexer
148167
-- A small set of keywords for a language with expressions of the form
149168
-- `let x = e in b`.
150169

151-
data TOK : Set where
152-
LET EQ IN : TOK
153-
LPAR RPAR : TOK
154-
ID : String TOK
170+
module LetIn where
171+
172+
data TOK : Set where
173+
LET EQ IN : TOK
174+
LPAR RPAR : TOK
175+
ID : String TOK
176+
177+
keywords : List# (String × TOK) (λ a b ⌊ ¬? ((proj₁ a) String.≟ (proj₁ b)) ⌋)
178+
keywords = ("let" , LET)
179+
∷# ("=" , EQ)
180+
∷# ("in" , IN)
181+
∷# []
155182

156-
toks : List⁺ (String × TOK)
157-
toks = ("let" , LET)
158-
∷ ("=" , EQ)
159-
∷ ("in" , IN)
160-
∷ []
183+
-- Breaking characters: spaces (thrown away) and parentheses (kept)
184+
breaking : Char ∃ (λ b if b then Maybe TOK else Lift 0ℓ ⊤)
185+
breaking c = if isSpace c then true , nothing else parens c where
161186

162-
-- Breaking characters: spaces (thrown away) and parentheses (kept)
187+
parens : Char _
188+
parens '(' = true , just LPAR
189+
parens ')' = true , just RPAR
190+
parens _ = false , _
163191

164-
breaking : Char λ b if b then Maybe TOK else Lift _ ⊤
165-
breaking c = if isSpace c then true , nothing else parens c where
192+
default : String TOK
193+
default = ID
166194

167-
parens : Char _
168-
parens '(' = true , just LPAR
169-
parens ')' = true , just RPAR
170-
parens _ = false , _
195+
letIn : Lexer 0ℓ
196+
letIn = record { LetIn }
171197

172198
open import Agda.Builtin.Equality
173-
open Lexer toks breaking ID
174199

175200
-- A test case:
176201

177-
_ : tokenize "fix f x = let b = fix f in (f b) x"
202+
open LetIn
203+
_ : tokenize letIn "fix f x = let b = fix f in (f b) x"
178204
≡ ID "fix"
179205
∷ ID "f"
180206
∷ ID "x"

README/Decidability.agda

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Examples of decision procedures and how to use them
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe #-}
8+
9+
module README.Decidability where
10+
11+
-- Reflects and Dec are defined in Relation.Nullary, and operations on them can
12+
-- be found in Relation.Nullary.Reflects and Relation.Nullary.Decidable.
13+
14+
open import Relation.Nullary as Nullary
15+
open import Relation.Nullary.Reflects
16+
open import Relation.Nullary.Decidable
17+
18+
open import Data.Bool
19+
open import Data.List
20+
open import Data.List.Properties using (∷-injective)
21+
open import Data.Nat
22+
open import Data.Nat.Properties using (suc-injective)
23+
open import Data.Product
24+
open import Data.Unit
25+
open import Function
26+
open import Relation.Binary.PropositionalEquality
27+
open import Relation.Nary
28+
open import Relation.Nullary.Product
29+
30+
infix 4 _≟₀_ _≟₁_ _≟₂_
31+
32+
-- A proof of `Reflects P b` shows that a proposition `P` has the truth value of
33+
-- the boolean `b`. A proof of `Reflects P true` amounts to a proof of `P`, and
34+
-- a proof of `Reflects P false` amounts to a refutation of `P`.
35+
36+
ex₀ : (n : ℕ) Reflects (n ≡ n) true
37+
ex₀ n = ofʸ refl
38+
39+
ex₁ : (n : ℕ) Reflects (zero ≡ suc n) false
40+
ex₁ n = ofⁿ λ ()
41+
42+
ex₂ : (b : Bool) Reflects (T b) b
43+
ex₂ false = ofⁿ id
44+
ex₂ true = ofʸ tt
45+
46+
-- A proof of `Dec P` is a proof of `Reflects P b` for some `b`.
47+
-- `Dec P` is declared as a record, with fields:
48+
-- does : Bool
49+
-- proof : Reflects P does
50+
51+
ex₃ : (b : Bool) Dec (T b)
52+
does (ex₃ b) = b
53+
proof (ex₃ b) = ex₂ b
54+
55+
-- We also have pattern synonyms `yes` and `no`, allowing both fields to be
56+
-- given at once.
57+
58+
ex₄ : (n : ℕ) Dec (zero ≡ suc n)
59+
ex₄ n = no λ ()
60+
61+
-- It is possible, but not ideal, to define recursive decision procedures using
62+
-- only the `yes` and `no` patterns. The following procedure decides whether two
63+
-- given natural numbers are equal.
64+
65+
_≟₀_ : (m n : ℕ) Dec (m ≡ n)
66+
zero ≟₀ zero = yes refl
67+
zero ≟₀ suc n = no λ ()
68+
suc m ≟₀ zero = no λ ()
69+
suc m ≟₀ suc n with m ≟₀ n
70+
... | yes p = yes (cong suc p)
71+
... | no ¬p = no (¬p ∘ suc-injective)
72+
73+
-- In this case, we can see that `does (suc m ≟ suc n)` should be equal to
74+
-- `does (m ≟ n)`, because a `yes` from `m ≟ n` gives rise to a `yes` from the
75+
-- result, and similarly for `no`. However, in the above definition, this
76+
-- equality does not hold definitionally, because we always do a case split
77+
-- before returning a result. To avoid this, we can return the `does` part
78+
-- separately, before any pattern matching.
79+
80+
_≟₁_ : (m n : ℕ) Dec (m ≡ n)
81+
zero ≟₁ zero = yes refl
82+
zero ≟₁ suc n = no λ ()
83+
suc m ≟₁ zero = no λ ()
84+
does (suc m ≟₁ suc n) = does (m ≟₁ n)
85+
proof (suc m ≟₁ suc n) with m ≟₁ n
86+
... | yes p = ofʸ (cong suc p)
87+
... | no ¬p = ofⁿ (¬p ∘ suc-injective)
88+
89+
-- We now get definitional equalities such as the following.
90+
91+
_ : (m n : ℕ) does (5 + m ≟₁ 3 + n) ≡ does (2 + m ≟₁ n)
92+
_ = λ m n refl
93+
94+
-- Even better, from a maintainability point of view, is to use `map` or `map′`,
95+
-- both of which capture the pattern of the `does` field remaining the same, but
96+
-- the `proof` field being updated.
97+
98+
_≟₂_ : (m n : ℕ) Dec (m ≡ n)
99+
zero ≟₂ zero = yes refl
100+
zero ≟₂ suc n = no λ ()
101+
suc m ≟₂ zero = no λ ()
102+
suc m ≟₂ suc n = map′ (cong suc) suc-injective (m ≟₂ n)
103+
104+
_ : (m n : ℕ) does (5 + m ≟₂ 3 + n) ≡ does (2 + m ≟₂ n)
105+
_ = λ m n refl
106+
107+
-- `map′` can be used in conjunction with combinators such as `_⊎-dec_` and
108+
-- `_×-dec_` to build complex (simply typed) decision procedures.
109+
110+
module ListDecEq₀ {a} {A : Set a} (_≟ᴬ_ : (x y : A) Dec (x ≡ y)) where
111+
112+
_≟ᴸᴬ_ : (xs ys : List A) Dec (xs ≡ ys)
113+
[] ≟ᴸᴬ [] = yes refl
114+
[] ≟ᴸᴬ (y ∷ ys) = no λ ()
115+
(x ∷ xs) ≟ᴸᴬ [] = no λ ()
116+
(x ∷ xs) ≟ᴸᴬ (y ∷ ys) =
117+
map′ (uncurry (cong₂ _∷_)) ∷-injective (x ≟ᴬ y ×-dec xs ≟ᴸᴬ ys)
118+
119+
-- The final case says that `x ∷ xs ≡ y ∷ ys` exactly when `x ≡ y` *and*
120+
-- `xs ≡ ys`. The proofs are updated by the first two arguments to `map′`.
121+
122+
-- In the case of ≡-equality tests, the pattern
123+
-- `map′ (congₙ c) c-injective (x₀ ≟ y₀ ×-dec ... ×-dec xₙ₋₁ ≟ yₙ₋₁)`
124+
-- is captured by `≟-mapₙ n c c-injective (x₀ ≟ y₀) ... (xₙ₋₁ ≟ yₙ₋₁)`.
125+
126+
module ListDecEq₁ {a} {A : Set a} (_≟ᴬ_ : (x y : A) Dec (x ≡ y)) where
127+
128+
_≟ᴸᴬ_ : (xs ys : List A) Dec (xs ≡ ys)
129+
[] ≟ᴸᴬ [] = yes refl
130+
[] ≟ᴸᴬ (y ∷ ys) = no λ ()
131+
(x ∷ xs) ≟ᴸᴬ [] = no λ ()
132+
(x ∷ xs) ≟ᴸᴬ (y ∷ ys) = ≟-mapₙ 2 _∷_ ∷-injective (x ≟ᴬ y) (xs ≟ᴸᴬ ys)

lib.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: lib
2-
version: 1.2-dev
2+
version: 1.2
33
cabal-version: >= 1.10
44
build-type: Simple
55
description: Helper programs.

0 commit comments

Comments
 (0)