Skip to content

Commit b5ce811

Browse files
committed
alternative 5 tutorial part (questionable)
1 parent c3787a7 commit b5ce811

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# 5. Mixing Manual and Automatic Generation
2+
3+
In the [previous tutorial](04-automatic-generator-derivation.md), we saw how `deriveGen` can automatically create generators for complex types. We also saw how to give it "hints" for primitive types like `String` using the `=>` syntax.
4+
5+
But what if you have a custom data type that needs a special, handwritten generator? `DepTyCheck` provides a powerful, "magic" feature: if you define a generator for a type, `deriveGen` will automatically find it and use it.
6+
7+
### Our Goal
8+
9+
We will define a `SpecialString` newtype and write a custom generator for it. We will then create a larger `User` type that contains a `SpecialString` and see how `deriveGen` automatically discovers and integrates our manual generator without any special syntax.
10+
11+
### Prerequisites
12+
13+
This tutorial assumes you have completed [Tutorial 4: Automatic Generator Derivation](04-automatic-generator-derivation.md).
14+
15+
---
16+
17+
## Step 1: A Type That Needs a Custom Generator
18+
19+
Imagine we have a `SpecialString` type that should only ever contain specific, predefined values (e.g., usernames with special privileges). A fully random `String` generator is not appropriate here.
20+
21+
1. **Create a new file** named `Mixed.idr`.
22+
23+
2. **Define the types and a handwritten generator.**
24+
25+
```idris
26+
module Mixed
27+
28+
import Test.DepTyCheck.Gen
29+
import Test.DepTyCheck.Runner
30+
import Data.Fuel
31+
32+
-- A type that needs special generation
33+
data SpecialString = MkSpecialString String
34+
35+
-- Standard domain types
36+
data User = MkUser SpecialString Nat
37+
38+
-- A handwritten generator for SpecialString
39+
genSpecialString : Fuel -> Gen MaybeEmpty SpecialString
40+
genSpecialString _ = map MkSpecialString (elements ["admin", "root", "system"])
41+
```
42+
We have defined `genSpecialString` to only produce three possible values. Notice it has the standard `Fuel -> Gen MaybeEmpty ...` signature.
43+
44+
## Step 2: Automatic Derivation Finds the Manual Generator
45+
46+
Now, let's define a generator for `User` using `deriveGen`. A `User` contains a `SpecialString` and a `Nat`. `deriveGen` knows how to generate a `Nat` by default. What will it do for `SpecialString`?
47+
48+
1. **Add the derived generator** to `Mixed.idr`.
49+
50+
```idris
51+
%language ElabReflection
52+
53+
-- Add deriveGen for the User
54+
genUser : Fuel -> Gen MaybeEmpty User
55+
genUser = deriveGen
56+
```
57+
58+
2. **Test it in the REPL.** Load your `Mixed.idr` file.
59+
60+
```idris
61+
:exec pick1 (genUser (limit 10))
62+
-- MkUser (MkSpecialString "root") 5 : User
63+
64+
:exec pick1 (genUser (limit 10))
65+
-- MkUser (MkSpecialString "admin") 12 : User
66+
```
67+
68+
It works! `deriveGen` automatically found and used our `genSpecialString` function when it needed to produce a `SpecialString`. It did this simply by looking for a function in the current scope with the required type signature (`... -> Gen ... SpecialString`).
69+
70+
## When to Use Implicit vs. Explicit (`=>`) Generation
71+
72+
`DepTyCheck` now offers two ways to combine generators:
73+
74+
1. **Implicit (this tutorial):** `deriveGen` automatically finds a generator in scope for a specific custom type (`SpecialString`).
75+
* **When to use:** This is the best method when you have a custom data type and you *always* want to use one specific generator for it.
76+
77+
2. **Explicit (`=>` syntax):** As seen in Tutorial 4, you can add a `(Fuel -> Gen MaybeEmpty String) =>` constraint to the signature.
78+
* **When to use:** This is best when you want to provide a generator for a *primitive* or *built-in* type (like `String`, `Nat`, `List`), or when you want the caller to be able to supply *different* generators in different contexts.
79+
80+
## Congratulations!
81+
82+
You've learned how to seamlessly mix automatic and manual generation, giving you the perfect balance of convenience and control.
83+
84+
### Next Steps
85+
86+
* **Continue to the next tutorial:** [Generating GADTs and Proof-Carrying Data](./06_generating_gadts.md) to see how these techniques apply to even more advanced types.

0 commit comments

Comments
 (0)