You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+54-4Lines changed: 54 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,24 +3,74 @@ A property testing framework for Lean 4 that integrates into the tactic framewor
3
3
4
4
## New Metaprogramming Code
5
5
See the [`New`](./Plausible/New/) subdirectory for code that uses Lean's metaprogramming facilities (`TSyntax`)
6
-
to automatically derive generators/checkers for inductive relations, à la [Paraskevopoulou et al. 2022](https://lemonidas.github.io/pdf/ComputingCorrectly.pdf).
6
+
to automatically derive generators/checkers for inductive relations.
7
+
8
+
Our design is heavily inspired by [Coq/Rocq's QuickChick](https://github.com/QuickChick/QuickChick) library and the following papers:
9
+
-[Computing Correctly with Inductive Relation (PLDI 2022)](https://lemonidas.github.io/pdf/ComputingCorrectly.pdf)
10
+
-[Generating Good Generators for Inductive Relations (POPL 2018)](https://lemonidas.github.io/pdf/GeneratingGoodGenerators.pdf)
11
+
12
+
Like QuickChick & [Haskell QuickChick](https://hackage.haskell.org/package/QuickCheck), we provide the following typeclasses for random generation:
13
+
-`Arbitrary`: random generators for inhabitants of algebraic data types
14
+
-`ArbitrarySuchThat`: generators which only produce random values that satisfy a user-supplied inductive relation
15
+
-`ArbitrarySized`, `ArbitrarySizedSuchThat`: versions of the two typeclasses above where the generator's size parameter is made explicit
16
+
17
+
We provide two top-level commands which automatically derive generators for Lean `inductive`s:
18
+
19
+
**1. Deriving unconstrained generators**
20
+
An *unconstrained* generator produces random inhabitants of an algebraic data type.
21
+
We provide two frontends which derive instances of `Arbitrary` & `ArbitrarySuchThat` respectively:
22
+
23
+
**1a. Deriving Instance** (for algebraic data types)
24
+
Users can write `deriving Arbitrary` after an inductive type definition:
25
+
26
+
```lean
27
+
inductive Tree where
28
+
...
29
+
deriving Arbitrary
30
+
```
31
+
32
+
Alternatively, users can also write `deriving instance Arbitrary for T1, ..., Tn` as a top-level command
33
+
to derive `Arbitrary` instances for types `T1, ..., Tn` simultaneously.
34
+
35
+
**1b. Command Elaborator**
36
+
We provide a command elaborator which elaborates the `#derive_arbitrary` command:
7
37
8
-
We provide two commands which automatically derive generators for Lean inductives:
9
38
```lean
10
-
-- `#derive_arbitrary` derives an unconstrained generator for a `Tree` algebraic data type
39
+
-- `#derive_arbitrary` derives an instance of `Arbitrary` for the `Tree` datatype
11
40
#derive_arbitrary Tree
41
+
```
12
42
43
+
Regardless of which frontend is used, to sample from the derived generator, users can simply call `runArbitrary` and specify some
44
+
`Nat` to act as the generator's size parameter (`10` in the example below):
A *constrained* generator only produces random values that satisfy a user-specified inductive relation.
52
+
We provide a command elaborator which elaborates the `#derive_generator` command:
53
+
54
+
```lean
13
55
-- `#derive_generator` derives a constrained generator for `Tree`s that are balanced at some height `n`,
14
56
-- where `balanced n t` is a user-defined inductive relation
15
57
#derive_generator (fun (t : Tree) => balanced n t)
58
+
``
59
+
60
+
To sample from the derived generator, users invoke `runSizedGen` & specify the right
61
+
instance of the `ArbitrarySizedSuchThat` typeclass (along with some `Nat` to act as the generator size):
62
+
63
+
```lean
64
+
#eval runSizedGen (ArbitrarySizedSuchThat.arbitrarySizedST (fun t => balanced 5 t)) 10
16
65
```
17
66
67
+
18
68
**Repo overview**:
19
69
20
70
-[`OptionTGen.lean`](./Plausible/New/OptionTGen.lean): Generator combinators that work over the `OptionT Gen` monad transformer (representing generators that may fail)
21
71
-[`DecOpt.lean`](./Plausible/New/DecOpt.lean): The `DecOpt` typeclass for partially decidable propositions, adapted from QuickChick
22
72
-[`Arbitrary.lean`](./Plausible/New/Arbitrary.lean): The `Arbitrary` & `ArbitrarySized` typeclasses for unconstrained generators, adapted from QuickChick
23
-
-[`ArbitrarySizedSuchThat.lean`](./Plausible/New/ArbitrarySizedSuchThat.lean): The `ArbitrarySuchThat` & `ArbitrarySizedSuchThat` typeclasses for constrained generators (generators of values satisfying a proposition), adapted from QuickChick
73
+
-[`ArbitrarySizedSuchThat.lean`](./Plausible/New/ArbitrarySizedSuchThat.lean): The `ArbitrarySuchThat` & `ArbitrarySizedSuchThat` typeclasses for constrained generators, adapted from QuickChick
24
74
-[`GeneratorCombinators.lean`](./Plausible/New/GeneratorCombinators.lean): Extra combinators for Plausible generators (e.g. analogs of the `sized` and `frequency` combinators from Haskell QuickCheck)
25
75
-[`DeriveArbitrary.lean`](./Plausible/New/DeriveArbitrary.lean): Metaprogramming infrastructure for deriving *unconstrained* generators (instances of the `ArbitrarySized` typeclass)
26
76
-[`DeriveGenerator.lean`](./Plausible/New/DeriveGenerator.lean): Metaprogramming infrastructure for deriving *constrained* generators (instances of the `ArbitrarySizedSuchThat` typeclass)
0 commit comments