on master help sign in
add documentation for elaboration reflection
commitd748d5e7aaeb5a701a52c46f245f4f0642505195 authorMartin Baker <git87465@martinb.com> dateWed 8 May 2019, 16:21 (7 years ago) parented4d4cf
21 files changed+1603
docs/_static/theme_overrides.css+13 docs/conf.py+6 docs/image/binders.png docs/image/compareToProofAssist.png docs/image/elab.png docs/image/elabLogicEx1_1.png docs/image/elabLogicEx1_2.png docs/image/elabLogicEx1_3.png docs/image/elabLogicEx1_4.png docs/image/elabOverview.png docs/image/elabProofState.png docs/image/elabProofStateEx1_1.png docs/image/elabProofStateEx1_2.png docs/image/elabProofStateEx1_3.png docs/image/idrisTopLevel.png docs/image/tree.png docs/proofs/elabReflection.rst+55 docs/proofs/example1.rst+280 docs/proofs/generatingData.rst+301 docs/proofs/primative.rst+517 docs/proofs/tactics.rst+431
docs/_static/theme_overrides.cssnew file+13
@@ -0,0 +1,13 @@
1+/* override table width restrictions */
2+@media screen and (min-width: 767px) {
3+
4+ .wy-table-responsive table td {
5+ /* !important prevents the common CSS stylesheets from overriding
6+ this as on RTD they are loaded after this stylesheet */
7+ white-space: normal !important;
8+ }
9+
10+ .wy-table-responsive {
11+ overflow: visible !important;
12+ }
13+}
docs/conf.py+6
@@ -151,6 +151,12 @@ if not on_rtd: # only import and set the theme if we're building docs locally
151151# so a file named "default.css" will overwrite the builtin "default.css".
152152html_static_path = ['_static']
153153
154+html_context = {
155+ 'css_files': [
156+ '_static/theme_overrides.css', # override wide tables in RTD theme
157+ ],
158+ }
159+
154160# Add any extra paths that contain custom files (such as robots.txt or
155161# .htaccess) here, relative to this directory. These files are copied
156162# directly to the root of the documentation.
docs/image/binders.pngnew file

Binary file not shown.

docs/image/compareToProofAssist.pngnew file

Binary file not shown.

docs/image/elab.pngnew file

Binary file not shown.

docs/image/elabLogicEx1_1.pngnew file

Binary file not shown.

docs/image/elabLogicEx1_2.pngnew file

Binary file not shown.

docs/image/elabLogicEx1_3.pngnew file

Binary file not shown.

docs/image/elabLogicEx1_4.pngnew file

Binary file not shown.

docs/image/elabOverview.pngnew file

Binary file not shown.

docs/image/elabProofState.pngnew file

Binary file not shown.

docs/image/elabProofStateEx1_1.pngnew file

Binary file not shown.

docs/image/elabProofStateEx1_2.pngnew file

Binary file not shown.

docs/image/elabProofStateEx1_3.pngnew file

Binary file not shown.

docs/image/idrisTopLevel.pngnew file

Binary file not shown.

docs/image/tree.pngnew file

Binary file not shown.

docs/proofs/elabReflection.rstnew file+55
@@ -0,0 +1,55 @@
1+Extending Idris using Elaborator Reflection
2+===========================================
3+
4+Idris provides a mechanism to modify the language without having to recompile Idris itself. We can think of this in terms of metaprogramming or domain specific languages or just building in new capabilities.
5+
6+In order to extend the language we need to know something about how Idris is complied. On this page we try to limit this explanation to only what we need to customise the elaboration. For more details of the compiler see `Edwin Brady 2013 paper`_ and for customising the elaboration process see `David Christiansen Practical Reflection and Metaprogramming`_ and `Elaborator reflection: extending Idris in Idris`_. For more information about holes and guesses see `Dependently Typed Functional Programs and their Proofs McBride 1999`_.
7+
8+Here is a diagram of the multistage process at the top level when Idris code gets compiled:
9+
10+.. image:: image/idrisTopLevel.png
11+ :width: 484px
12+ :height: 147px
13+
14+TT is a core language which is syntactically very simple, this makes it easy for computers to process but very verbose and hard for humans to read. This elaboration is done by a logic language (proof tactics) similar to LTac in Coq. Here we use the word 'tactics' to refer to these elaboration tactics - not to be confused with the old tactics mechanism.
15+
16+.. image:: image/compareToProofAssist.png
17+ :width: 229px
18+ :height: 114px
19+
20+This gives the opportunity to allow the primitives of the elaboration mechanism to be exposed to metaprograms.
21+During elaboration TT (Raw) structure contains:
22+
23+- holes - terms yet to be inferred.
24+- guesses - Suppresses β-reduction while precise structure not known.
25+
26+Type checker:
27+
28+- include universe levels
29+- distinguish between global and local bound names.
30+
31+.. image:: image/elabOverview.png
32+ :width: 268px
33+ :height: 219px
34+
35+As already mentioned the TT core language is kept syntactically very simple. Part of the reason for this is that its correctness is already well proven using logic. For instance, here are the binders in TT with corresponding code and logic type introduction rules:
36+
37+.. image:: image/binders.png
38+ :width: 310px
39+ :height: 203px
40+
41+.. list-table::
42+
43+ * - There is an elaborator for both definitions and terms, the definition elaborator calls the term elaborator when required.
44+ - .. image:: image/elab.png
45+ :width: 141px
46+ :height: 145px
47+
48+.. target-notes::
49+.. _`Edwin Brady 2013 paper`: https://eb.host.cs.st-andrews.ac.uk/drafts/impldtp.pdf
50+.. _`David Christiansen Practical Reflection and Metaprogramming`: https://davidchristiansen.dk/david-christiansen-phd.pdf
51+.. _`Elaborator reflection: extending Idris in Idris`: https://dl.acm.org/citation.cfm?doid=2951913.2951932
52+.. _`Dependently Typed Functional Programs and their Proofs McBride 1999`: https://www.era.lib.ed.ac.uk/handle/1842/374
53+
54+
55+
docs/proofs/example1.rstnew file+280
@@ -0,0 +1,280 @@
1+Example 1
2+=========
3+
4+.. list-table:: Nat identity
5+
6+ * - As an example of elaborator reflection here we step through this identity implementation:
7+ - Nat identity.
8+
9+ .. code-block:: idris
10+
11+ %language ElabReflection
12+
13+ idNat : Nat -> Nat
14+ idNat = %runElab (do
15+ intro `{{x}}
16+ fill (Var `{{x}})
17+ solve
18+ )
19+
20+.. list-table:: Nat identity
21+
22+ * - We start off with a hole for the whole term (of type Nat->Nat).
23+ We fill that with 'intro' which creates a lambda term with a hole for the expression.
24+ - diagram
25+
26+ .. image:: image/tree.png
27+ :width: 133px
28+ :height: 106px
29+
30+After each tactic we will look at the state:
31+
32+.. list-table:: evolution of state
33+
34+ * - We start with the type signature like this:
35+ - Nat identity.
36+
37+ .. code-block:: idris
38+
39+ %language ElabReflection
40+
41+ idNat : Nat -> Nat
42+ idNat = %runElab (do
43+
44+ * - In order to investigate how the program works we can look at the proofState at each stage as the tactics are applied. So here is the proofState at the start:
45+ - state
46+
47+ .. image:: image/elabProofStateEx1_1.png
48+ :width: 310px
49+ :height: 124px
50+
51+ * - We can also look at the logic at each stage:
52+ - logic
53+
54+ .. image:: image/elabLogicEx1_1.png
55+ :width: 126px
56+ :height: 33px
57+
58+ * - The term is:
59+ - ?{hole_0} ≈ ? {hole_2} . {hole_2} . {hole_0}
60+
61+ * - getEnv
62+
63+ getGoal
64+
65+ getHoles
66+
67+ - state.
68+
69+ .. code-block:: idris
70+
71+ getEnv=[]
72+
73+ getGoal=({hole_2}, {TT:Bind
74+ name=`{{__pi_arg}}
75+ binder={
76+ Π ({`{{Nat}}.["Nat", "Prelude"]}:{type const tag=8,0}).{
77+ TT:TType tt=ext=./Prelude/Nat.idr#20
78+ }
79+ }
80+ tt={
81+ TT:Parameter name ref
82+ NameType={type const tag=8,0}
83+ TTName={`{{Nat}}.["Nat","Prelude"]}
84+ TT={TT:TType
85+ tt=ext=./Prelude/Nat.idr#20
86+ }
87+ }
88+ })
89+
90+ getHoles=[{hole_2},{hole_0}]
91+
92+ * - getGuess
93+ - error no guess
94+
95+ * - Introduce a lambda binding around the current hole and focus on the body.
96+ - intro \`{{x}}
97+
98+ * - state now looks like this
99+ - state
100+
101+ .. image:: image/elabProofStateEx1_2.png
102+ :width: 312px
103+ :height: 124px
104+
105+ * - logic now looks like this
106+ - logic
107+
108+ .. image:: image/elabLogicEx1_2.png
109+ :width: 126px
110+ :height: 45px
111+
112+ * - term now looks like this
113+ - ?{hole_0} ≈ λ x . ? {hole_2} . {hole_2} . {hole_0}
114+
115+ * - getEnv
116+
117+ getGoal
118+
119+ getHoles
120+
121+ - state.
122+
123+ .. code-block:: idris
124+
125+ getEnv=[(
126+ `{{x}}, {
127+ λ ({`{{Nat}}.["Nat", "Prelude"]}:{type const tag=8,0}).
128+ {TT:TType
129+ tt=ext=./Prelude/Nat.idr#20
130+ }
131+ }
132+ )]
133+
134+ getGoal=({hole_2},{
135+ TT:Parameter name ref
136+ NameType={type const tag=8,0}
137+ TTName={`{{Nat}}.["Nat", "Prelude"]}
138+ TT={TT:TType
139+ tt=ext=./Prelude/Nat.idr#20
140+ }
141+ }
142+ )
143+
144+ getHoles=[{hole_2},{hole_0}]
145+
146+ * - getGuess
147+ - error no guess
148+
149+ * - Place a term into a hole, unifying its type
150+ - fill (Var \`{{x}})
151+
152+ * - state now looks like this
153+ - state
154+
155+ .. image:: image/elabProofStateEx1_3.png
156+ :width: 312px
157+ :height: 124px
158+
159+ * - logic now looks like this
160+ - logic
161+
162+ .. image:: image/elabLogicEx1_3.png
163+ :width: 131px
164+ :height: 45px
165+
166+ * - term
167+ - ?{hole_0} ≈ λ x . ?{hole_2} ≈ x . {hole_2} . {hole_0}
168+
169+ * - getEnv
170+
171+ getGoal
172+
173+ getHoles
174+
175+ - state.
176+
177+ .. code-block:: idris
178+
179+ getEnv=[(`{{x}}, {λ ({`{{Nat}}.["Nat", "Prelude"]}:
180+ {type const tag=8,0}).
181+ {TT:TType
182+ tt=ext=./Prelude/Nat.idr#20
183+ }
184+ }
185+ )]
186+
187+ getGoal=({hole_2},
188+ {TT:Parameter name ref
189+ NameType={type const tag=8,0}
190+ TTName={`{{Nat}}.["Nat", "Prelude"]}
191+ TT={TT:TType
192+ tt=ext=./Prelude/Nat.idr#20
193+ }
194+ })
195+
196+ getHoles=[{hole_2}, {hole_0}]
197+
198+ * - getGuess
199+ - state.
200+
201+ .. code-block:: idris
202+
203+ {TT:Parameter name ref
204+ NameType=NameType just bound by intro
205+ TTName=`{{x}}
206+ TT={TT:Parameter name ref
207+ NameType={type const tag=8,0}
208+ TTName={`{{Nat}}.["Nat", "Prelude"]}
209+ TT={TT:TType
210+ tt=ext=./Prelude/Nat.idr#20
211+ }
212+ }
213+ }
214+
215+ * - Substitute a guess into a hole.
216+ - solve
217+
218+ * - logic now looks like this
219+ - logic
220+
221+ .. image:: image/elabLogicEx1_4.png
222+ :width: 131px
223+ :height: 14px
224+
225+ * - term
226+ - ?{hole_0} ≈ λ x . x . {hole_0}
227+
228+ * - getEnv
229+
230+ getGoal
231+
232+ getHoles
233+
234+ - state.
235+
236+ .. code-block:: idris
237+
238+ getEnv=[]
239+
240+ getGoal=({hole_0}, {TT:Bind
241+ name=`{{__pi_arg}}
242+ binder={
243+ Π ({`{{Nat}}.["Nat", "Prelude"]}:
244+ {type const tag=8,0}).{TT:TType
245+ tt=ext=./Prelude/Nat.idr#20
246+ }
247+ }
248+ tt={TT:Parameter name ref
249+ NameType={type const tag=8,0}
250+ TTName={`{{Nat}}.["Nat","Prelude"]}
251+ TT={TT:TType tt=ext=./Prelude/Nat.idr#20}
252+ }
253+ })
254+
255+ getHoles=[{hole_0}]
256+
257+ * - getGuess
258+ - state.
259+
260+ .. code-block:: idris
261+
262+ {TT:Bind
263+ name=`{{x}}
264+ binder={λ ({`{{Nat}}.["Nat","Prelude"]}:{type const tag=8,0}).{
265+ TT:TType
266+ tt=ext=./Prelude/Nat.idr#20
267+ }
268+ }
269+ tt={TT:Parameter name ref
270+ NameType=NameType just bound by intro
271+ TTName=`{{x}}
272+ TT={TT:Parameter name ref
273+ NameType={type const tag=8,0}
274+ TTName={`{{Nat}}.["Nat", "Prelude"]}
275+ TT={TT:TType
276+ tt=ext=./Prelude/Nat.idr#20
277+ }
278+ }
279+ }
280+ }
docs/proofs/generatingData.rstnew file+301
@@ -0,0 +1,301 @@
1+Generating Data and Functions at Compile Time
2+=============================================
3+
4+We can construct a data structure at compile-time in an Elab monad.
5+This can allow proofs to be generated for user defined types or it could allow types to be automatically generated to support user defined types.
6+An example is the code, from <a href="https://dl.acm.org/citation.cfm?id=2951932">Christensen-Brady joint paper</a> ('Elaborator Reflection: Extending Idris in Idris'), that automatically generates accessibility predicates using the Bove-Capretta method.
7+The following simple outline example is adapted from
8+`<https://github.com/idris-lang/Idris-dev/blob/master/test/meta002/DataDef.idr>`_
9+
10+.. code-block:: idris
11+
12+ module DataDef
13+ %language ElabReflection
14+
15+ addData : Elab ()
16+ addData = do
17+ let dataname : TTName = `{{DataDef.N}}
18+ declareDatatype $ Declare dataname [MkFunArg `{{n}} `(Nat) Explicit NotErased] `(Type)
19+ defineDatatype $ DefineDatatype dataname [
20+ Constructor `{{MkN}} [MkFunArg `{{x}} `(Nat) Implicit NotErased]
21+ (RApp (Var `{{DataDef.N}}) (Var `{{x}})),
22+ Constructor `{{MkN'}} [MkFunArg `{{x}} `(Nat) Explicit NotErased]
23+ (RApp (Var `{{DataDef.N}}) (RApp (Var `{S}) (Var `{{x}})))
24+ ]
25+
26+ %runElab addData
27+
28+So this declares and defines the following data structure 'N' with a constructor 'MkN' which can have an implicit or an explicit Nat argument.
29+
30+.. code-block:: idris
31+
32+ data N : Nat -> Type where
33+ MkN : N x
34+ MkN' : (x : Nat) -> N (S x)
35+
36+Which can be used like this:
37+
38+.. code-block:: idris
39+
40+ λΠ> :t N
41+ N : Nat -> Type
42+ λΠ> N 2
43+ N 2 : Type
44+ λΠ> N 0
45+ N 0 : Type
46+ λΠ> :t MkN
47+ MkN : N x
48+
49+Here is another, more complicated, example from the same test file. This also creates a function.
50+
51+.. code-block:: idris
52+
53+ module DataDef
54+ %language ElabReflection
55+
56+ mkU : Elab ()
57+ mkU = do
58+ let U = `{{DataDef.U}}
59+ let el = `{{DataDef.el}}
60+ declareDatatype $ Declare U [] `(Type)
61+ declareType $ Declare el [MkFunArg `{{code}} (Var U) Explicit NotErased] `(Type)
62+ defineDatatype $ DefineDatatype U [
63+ Constructor `{{Base}} [] (Var U),
64+ Constructor `{{Pi}}
65+ [MkFunArg `{{code}} (Var U) Explicit NotErased,
66+ MkFunArg `{{body}} `(~(RApp (Var el) (Var `{{code}})) -> ~(Var U)) Explicit NotErased]
67+ (Var U)
68+ ]
69+ defineFunction $ DefineFun el [
70+ MkFunClause (RBind `{{code}} (PVar (Var U))
71+ (RBind `{{body}} (PVar `(~(RApp (Var el) (Var `{{code}})) -> ~(Var U)))
72+ (RApp (Var el)
73+ (RApp (RApp (Var `{{DataDef.Pi}})
74+ (Var `{{code}}))
75+ (Var `{{body}})))))
76+ (RBind `{{code}} (PVar (Var U))
77+ (RBind `{{body}} (PVar `(~(RApp (Var el) (Var `{{code}})) -> ~(Var U)))
78+ (RBind `{{x}} (Pi (RApp (Var el) (Var `{{code}})) `(Type))
79+ (RApp (Var el) (RApp (Var `{{body}}) (Var `{{x}})))))),
80+ MkFunClause (RApp (Var el) (Var `{{DataDef.Base}})) `(Bool)
81+ ]
82+
83+ %runElab mkU
84+
85+This code generates the following data and function:
86+
87+.. code-block:: idris
88+
89+data U : Type where
90+ Base : U
91+ Pi : (code : U) -> (el code -> U) -> U
92+ el : U -> Type
93+ el (Pi code body) = (x : el code) -> el (body x)
94+ el Base = Bool
95+
96+Which can be used like this:
97+
98+.. code-block:: idris
99+
100+ λΠ> :t U
101+ U : Type
102+ λΠ> :doc U
103+ No documentation for U
104+ λΠ> Base
105+ Base : U
106+ λΠ> DataDef.Pi
107+ Pi : (code : U) -> (el code -> U) -> U
108+
109+
110+.. code-block:: idris
111+
112+ λΠ> :t el
113+ el : U -> Type
114+ λΠ> el Base
115+ Bool : Type
116+
117+So these are the functions that we can use to create data and functions in the Elab monad:
118+
119+.. list-table:: Generating Data and Functions
120+ :widths: 10 30
121+ :stub-columns: 1
122+
123+ * - declareType
124+ - Add a type declaration to the global context.
125+
126+ Signature:
127+
128+ declareType : TyDecl -> Elab ()
129+ * - defineFunction
130+ - Define a function in the global context. The function must have already been declared, either in ordinary Idris code or using `declareType`.
131+
132+ Signature:
133+
134+ defineFunction : FunDefn Raw -> Elab ()
135+
136+ * - declareDatatype
137+ - Declare a datatype in the global context. This step only establishes the type constructor; use `defineDatatype` to give it constructors.
138+
139+ Signature:
140+
141+ declareDatatype : TyDecl -> Elab ()
142+
143+ * - defineDatatype
144+ - Signature:
145+
146+ defineDatatype : DataDefn -> Elab ()
147+
148+ * - addImplementation
149+ - Register a new implementation for interface resolution.
150+
151+ - @ ifaceName the name of the interface for which an implementation is being registered
152+ - @ implName the name of the definition to use in implementation search
153+
154+ Signature:
155+
156+ addImplementation : (ifaceName, implName : TTName) -> Elab ()
157+
158+ * - isTCName
159+ - Determine whether a name denotes an interface.
160+
161+ @ name a name that might denote an interface.
162+
163+ Signature:
164+
165+ isTCName : (name : TTName) -> Elab Bool
166+
167+The above functions use the following data/records:
168+
169+.. list-table:: Generating Data and Functions data/records
170+ :widths: 10 30
171+ :stub-columns: 1
172+
173+ * - Plicity
174+ - How an argument is provided in high-level Idris
175+
176+ .. code-block:: idris
177+
178+ data Plicity=
179+ ||| The argument is directly provided at the application site
180+ Explicit |
181+ ||| The argument is found by Idris at the application site
182+ Implicit |
183+ ||| The argument is solved using interface resolution
184+ Constraint
185+
186+ * - FunArg
187+ - Function arguments
188+
189+ These are the simplest representation of argument lists, and are used for functions. Additionally, because a FunArg provides enough
190+ information to build an application, a generic type lookup of a top-level identifier will return its FunArgs, if applicable.
191+
192+ .. code-block:: idris
193+
194+ record FunArg where
195+ constructor MkFunArg
196+ name : TTName
197+ type : Raw
198+ plicity : Plicity
199+ erasure : Erasure
200+
201+ * - TyConArg
202+ - Type constructor arguments
203+
204+ Each argument is identified as being either a parameter that is
205+
206+ consistent in all constructors, or an index that varies based on
207+
208+ which constructor is selected.
209+
210+ .. code-block:: idris
211+
212+ data TyConArg =
213+ ||| Parameters are uniform across the constructors
214+ TyConParameter FunArg |
215+ ||| Indices are not uniform
216+ TyConIndex FunArg
217+
218+ * - TyDecl
219+ - A type declaration for a function or datatype
220+
221+ .. code-block:: idris
222+
223+ record TyDecl where
224+ constructor Declare
225+ ||| The fully-qualified name of the function or datatype being declared.
226+ name : TTName
227+ ||| Each argument is in the scope of the names of previous arguments.
228+ arguments : List FunArg
229+ ||| The return type is in the scope of all the argument names.
230+ returnType : Raw
231+
232+ * - FunClause
233+ - A single pattern-matching clause
234+
235+ .. code-block:: idris
236+
237+ data FunClause : Type -> Type where
238+ MkFunClause : (lhs, rhs : a) -> FunClause a
239+ MkImpossibleClause : (lhs : a) -> FunClause a
240+
241+ * - FunDefn
242+ - A reflected function definition.
243+
244+ .. code-block:: idris
245+
246+ record FunDefn a where
247+ constructor DefineFun
248+ name : TTName
249+ clauses : List (FunClause a)
250+
251+ * - ConstructorDefn
252+ - A constructor to be associated with a new datatype.
253+
254+ .. code-block:: idris
255+
256+ record ConstructorDefn where
257+ constructor Constructor
258+ ||| The name of the constructor. The name must _not_ be qualified -
259+ ||| that is, it should begin with the `UN` or `MN` constructors.
260+ name : TTName
261+ ||| The constructor arguments. Idris will infer which arguments are
262+ ||| datatype parameters.
263+ arguments : List FunArg
264+ ||| The specific type constructed by the constructor.
265+ returnType : Raw
266+
267+ * - DataDefn
268+ - A definition of a datatype to be added during an elaboration script.
269+
270+ .. code-block:: idris
271+
272+ record DataDefn where
273+ constructor DefineDatatype
274+ ||| The name of the datatype being defined. It must be
275+ ||| fully-qualified, and it must have been previously declared as a
276+ ||| datatype.
277+ name : TTName
278+
279+ * - CtorArg
280+ - CtorParameter
281+
282+ .. code-block:: idris
283+
284+ data CtorArg = CtorParameter FunArg | CtorField FunArg
285+
286+ * - Datatype
287+ - A reflected datatype definition
288+
289+ .. code-block:: idris
290+
291+ record Datatype where
292+ constructor MkDatatype
293+ ||| The name of the type constructor
294+ name : TTName
295+ ||| The arguments to the type constructor
296+ tyConArgs : List TyConArg
297+ ||| The result of the type constructor
298+ tyConRes : Raw
299+ ||| The constructors for the family
300+ constructors : List (TTName, List CtorArg, Raw)</td>
301+
docs/proofs/primative.rstnew file+517
@@ -0,0 +1,517 @@
1+Primitive Operators
2+===================
3+
4+.. list-table:: Primitive Operators
5+ :widths: 10 30
6+ :stub-columns: 1
7+
8+ * - gensym
9+ - Generate a unique name based on some hint.
10+
11+ Useful when establishing a new binder.
12+
13+ **NB**: the generated name is unique **for this run of the elaborator**.
14+
15+ Do not assume that they are globally unique.
16+
17+ Signature:
18+
19+ gensym : (hint : String) -> Elab TTName
20+
21+ * - solve
22+ - Substitute a guess into a hole.
23+
24+ Substitute the focused guess throughout its scope, eliminating it and moving focus to the next element of the hole queue. Fail if the focus is not a guess.
25+
26+ Signature:
27+
28+ solve : Elab ()
29+
30+ * - fill
31+ - Place a term into a hole, unifying its type. Fails if the focus is not a hole.
32+
33+ Signature:
34+
35+ fill : (e : Raw) -> Elab ()
36+
37+ Place a term e with type tc into the focused hole:
38+
39+ ?h : th.e'
40+
41+ and convert it to a guess:
42+
43+ ?h ≈ e:t.e'
44+
45+ and fail if the current focus is not a hole. The type t of the guess is constructed by unifying tc and th, which may instantiate holes that they refer to. Fail if the current focus is not a hole or if unification fails.
46+
47+ This unification can result in the solution of further holes or the establishment of additional unsolved unification constraints.
48+
49+ * - apply
50+ - Attempt to apply an operator to fill the current hole, potentially solving arguments by unification.
51+
52+ A hole is established for each argument.
53+
54+ The return value is the list of holes established for the arguments to the function.
55+
56+ Note that not all of the returned hole names still exist, as they may have been solved.
57+
58+ - @ op the term to apply
59+ - @ argSpec - A list of booleans, one for each argument that the operator will be applied to. If true then attempt to solve the argument by unification.
60+
61+ Signature:
62+
63+ apply : (op : Raw) -> (argSpec : List Bool) -> Elab (List TTName)
64+
65+ Example: elaborating an application of a function f that takes one implicit and two explicit arguments might invoke:
66+
67+ apply \`(f) [False, True, True]
68+
69+ Here is an example of an elab script that uses apply to insert the term plus Z (S Z) into a goal of type Nat.
70+
71+ .. code-block:: idris
72+
73+ do [x,y] <- apply `(plus) [False, False]
74+ solve
75+ focus x; fill `(Z); solve
76+ focus y; fill `(S Z); solve
77+
78+ The names of the established holes are returned.
79+
80+ Note: This was added to the original tactic language to allow elaborator reflection.
81+
82+ * - matchApply
83+ - Attempt to apply an operator to fill the current hole, potentially solving arguments by matching.
84+
85+ The return value is the list of holes established for the arguments to the function.
86+
87+ Note that not all of the returned hole names still exist, as they may have been solved.
88+
89+ - @ op the term to apply
90+ - @ argSpec instructions for finding the arguments to the term, where the Boolean states whether or not to attempt to solve the argument by matching.
91+
92+ Signature:
93+
94+ matchApply : (op : Raw) -> (argSpec : List Bool) -> Elab (List TTName)
95+
96+ * - focus
97+ - Move the focus to the specified hole, bringing it to the front of the hole queue. Fails if the hole does not exist.
98+
99+ @ hole the hole to focus on
100+
101+ Signature:
102+
103+ focus : (hole : TTName) -> Elab ()
104+
105+ * - unfocus
106+ - Send the currently-focused hole to the end of the hole queue and focus on the next hole.
107+
108+ Signature:
109+
110+ unfocus : TTName -> Elab ()
111+
112+ * - attack
113+ - Convert a hole to make it suitable for bindings - that is, transform it such that it has the form
114+
115+ `?h : t . h` as opposed to `?h : t . f h`.
116+
117+ The binding tactics require that a hole be directly under its binding, or else the scopes of the generated terms won't make sense. This tactic creates a new hole of the proper form, and points the old hole at it.
118+
119+ Signature:
120+
121+ attack : Elab ()
122+
123+ * - claim
124+ - Establish a new hole binding named n with type t, surrounding the current focus.
125+
126+ Introduce a new hole with a specified name and type.
127+
128+ The new hole will be focused, and the previously-focused hole will be immediately after it in the hole queue. Because this tactic introduces a new binding, you may need to 'attack' first.
129+
130+ Signature:
131+
132+ claim : TTName -> Raw -> Elab ()
133+
134+ * - patvar
135+ - Convert a hole into a pattern variable.
136+
137+ Signature:
138+
139+ patvar : TTName -> Elab ()
140+
141+ * - compute
142+ - Normalise the goal.
143+
144+ Often this is not necessary because normanisation is applied during other tactics.
145+
146+ Signature:
147+
148+ compute : Elab ()
149+
150+ * - normalise
151+ - Normalise a term in some lexical environment
152+
153+ - @ env the environment in which to compute (get one of these from `getEnv`)
154+ - @ term the term to normalise
155+
156+ Signature:
157+
158+ normalise : (env : List (TTName, Binder TT)) -> (term : TT) -> Elab TT
159+
160+ * - whnf
161+ - Reduce a closed term to weak-head normal form
162+
163+ @ term the term to reduce
164+
165+ Signature:
166+
167+ whnf : (term : TT) -> Elab TT
168+
169+ * - convertsInEnv
170+ - Check that two terms are convertible in the current context and in some environment.
171+
172+ - @ env a lexical environment to compare the terms in (see `getEnv`)
173+ - @ term1 the first term to convert
174+ - @ term2 the second term to convert
175+
176+ Signature:
177+
178+ convertsInEnv : (env : List (TTName, Binder TT)) -> (term1, term2 : TT) -> Elab ()
179+
180+ * - converts
181+ - Check that two terms are convertable in the current context and environment
182+
183+ - @ term1 the first term to convert
184+ - @ term2 the second term to convertconverts : (term1, term2 : TT) -> Elab ()
185+
186+ converts term1 term2 = convertsInEnv !getEnv term1 term2
187+
188+ * - getSourceLocation
189+ - Find the source context for the elaboration script
190+
191+ Signature:
192+
193+ getSourceLocation : Elab SourceLocation
194+
195+ * - sourceLocation
196+ - Attempt to solve the current goal with the source code
197+
198+ locationsourceLocation : Elab ()
199+
200+ .. code-block:: idris
201+
202+ sourceLocation = do loc <- getSourceLocation
203+ fill (quote loc)
204+ solve
205+
206+ * - currentNamespace
207+ - Get the current namespace at the point of tactic execution. This allows scripts to define top-level names conveniently.
208+
209+ The namespace is represented as a reverse-order list of strings, just as in the representation of names.
210+
211+ Signature:
212+
213+ currentNamespace : Elab (List String)
214+
215+ * - rewriteWith
216+ - Attempt to rewrite the goal using an equality.
217+
218+ The tactic searches the goal for applicable subterms, and constructs a context for `replace` using them. In some cases, this is not possible, and `replace` must be called manually with an appropriate context.
219+
220+ Because this tactic internally introduces a `let` binding, it requires that the hole be immediately under its binder (use 'attack' if it might not be).
221+
222+ Signature:
223+
224+ rewriteWith : Raw -> Elab ()
225+
226+ * - resolveTC
227+ - Attempt to solve the current goal with an interface dictionary
228+
229+ @ fn the name of the definition being elaborated (to prevent Idris from looping)
230+
231+ Signature:
232+
233+ resolveTC : (fn : TTName) -> Elab ()
234+
235+ * - search
236+ - Use Idris's internal proof search.
237+
238+ Signature:
239+
240+ search : Elab ()
241+
242+ * - search'
243+ - Use Idris's internal proof search, with more control.
244+
245+ - @ depth the search depth
246+ - @ hints additional names to try
247+
248+ Signature:
249+
250+ search' : (depth : Int) -> (hints : List TTName) -> Elab ()
251+
252+ * - operatorFixity
253+ - Look up the declared fixity for an operator.
254+
255+ The lookup fails if the operator does not yet have a fixity or if the string is not a valid operator.
256+
257+ @ operator the operator string to look up
258+
259+ Signature:
260+
261+ operatorFixity : (operator : String) -> Elab Fixity
262+
263+ * - debug
264+ - Halt elaboration, dumping the internal state for inspection.
265+
266+ This is intended for elaboration script developers, not for end-users. Use `fail` for final scripts.
267+
268+ Signature:
269+
270+ debug : Elab a
271+
272+ Only seems to compile if 'debug' is last tactic so comment out following tactics like this:
273+
274+ .. code-block:: idris
275+
276+ %language ElabReflection
277+
278+ idNat : Nat -> Nat
279+ idNat = %runElab (do
280+ intro `{{x}}
281+ debug
282+ -- fill (Var `{{x}})
283+ -- solve
284+ )
285+
286+ * - debugMessage
287+ - Halt elaboration, dumping the internal state and displaying a message.
288+
289+ This is intended for elaboration script developers, not for end-users. Use `fail` for final scripts.
290+
291+ @ msg the message to display
292+
293+ Signature:
294+
295+ debugMessage : (msg : List ErrorReportPart) -> Elab a
296+
297+ Only seems to compile if 'debug' is last tactic so comment out following tactics like this:
298+
299+ .. code-block:: idris
300+
301+ %language ElabReflection
302+ idNat : Nat -> Nat
303+ idNat = %runElab (do
304+ intro `{{x}}
305+ debugMessage [TextPart "error message"]
306+ -- fill (Var `{{x}})
307+ -- solve
308+ )
309+
310+ * - metavar
311+ - Create a new top-level metavariable to solve the current hole.
312+
313+ @ name the name for the top-level variable
314+
315+ Signature:
316+
317+ metavar : (name : TTName) -> Elab ()
318+
319+ * - runElab
320+ - Recursively invoke the reflected elaborator with some goal.
321+
322+ The result is the final term and its type.
323+
324+ Signature:
325+
326+ runElab : Raw -> Elab () -> Elab (TT, TT)
327+
328+
329+Read and Write State
330+====================
331+
332+.. list-table:: Read and Write State
333+ :widths: 10 30
334+ :stub-columns: 1
335+
336+ * - getEnv
337+ - Look up the lexical binding at the focused hole. Fails if no holes are present.
338+
339+ Signature:
340+
341+ getEnv : Elab (List (TTName, Binder TT))
342+
343+ * - getGoal
344+ - Get the name and type of the focused hole. Fails if not holes are present.
345+
346+ Signature:
347+
348+ getGoal : Elab (TTName, TT)
349+
350+ * - getHoles
351+ - Get the hole queue, in order.
352+
353+ Signature:
354+
355+ getHoles : Elab (List TTName)
356+
357+ * - getGuess
358+ - If the current hole contains a guess, return it. Otherwise, fail.
359+
360+ Signature:
361+
362+ getGuess : Elab TT
363+
364+ * - lookupTy
365+ - Look up the types of every overloading of a name.
366+
367+ Signature:
368+
369+ lookupTy : TTName -> Elab (List (TTName, NameType, TT))
370+
371+ * - lookupTyExact
372+ - Get the type of a fully-qualified name. Fail if it doesn't resolve uniquely.
373+
374+ Signature:
375+
376+ lookupTyExact : TTName -> Elab (TTName, NameType, TT)
377+
378+ .. code-block:: idris
379+
380+ lookupTyExact n = case !(lookupTy n) of
381+ [res] => pure res
382+ [] => fail [NamePart n, TextPart "is not defined."]
383+ xs => fail [NamePart n, TextPart "is ambiguous."]
384+
385+ * - lookupDatatype
386+ - Find the reflected representation of all datatypes whose names are overloadings of some name.
387+
388+ Signature:
389+
390+ lookupDatatype : TTName -> Elab (List Datatype)
391+
392+ * - lookupDatatypeExact
393+ - Find the reflected representation of a datatype, given its fully-qualified name. Fail if the name does not uniquely resolve to a datatype.
394+
395+ Signature:
396+
397+ lookupDatatypeExact : TTName -> Elab Datatype
398+
399+ .. code-block:: idris
400+
401+ lookupDatatypeExact n = case !(lookupDatatype n) of
402+ [res] => pure res
403+ [] => fail [TextPart
404+ "No datatype named", NamePart n]
405+ xs => fail [TextPart "More than one datatype named",
406+ NamePart n]
407+
408+ * - lookupFunDefn
409+ - Find the reflected function definition of all functions whose names are overloadings of some name.
410+
411+ Signature:
412+
413+ lookupFunDefn : TTName -> Elab (List (FunDefn TT))
414+
415+ * - lookupFunDefnExact
416+ - Find the reflected function definition of a function, given its fully-qualified name. Fail if the name does not uniquely resolve to a function.
417+
418+ Signature:
419+
420+ lookupFunDefnExact : TTName -> Elab (FunDefn TT)
421+
422+ .. code-block:: idris
423+
424+ lookupFunDefnExact n = case !(lookupFunDefn n) of
425+ [res] => pure res
426+ [] => fail [TextPart
427+ "No function named", NamePart n]
428+ xs => fail [TextPart "More than one function named",
429+ NamePart n]
430+ * - lookupArgs
431+ - Get the argument specification for each overloading of a name.
432+
433+ Signature:
434+
435+ lookupArgs : TTName -> Elab (List (TTName, List FunArg, Raw))
436+
437+ * - lookupArgsExact
438+ - Get the argument specification for a name. Fail if the name does not uniquely resolve.
439+
440+ Signature:
441+
442+ lookupArgsExact : TTName -> Elab (TTName, List FunArg, Raw)
443+
444+ .. code-block:: idris
445+
446+ lookupArgsExact n = case !(lookupArgs n) of
447+ [res] => pure res
448+ [] => fail [NamePart n, TextPart "is not defined."]
449+ xs => fail [NamePart n, TextPart "is ambiguous."]
450+
451+ * - check
452+ - Attempt to type-check a term, getting back itself and its type.
453+
454+ - @ env the environment within which to check the type
455+ - @ tm the term to check
456+
457+ Signature:
458+
459+ check : (env : List (TTName, Binder TT)) -> (tm : Raw) -> Elab (TT, TT)
460+
461+Error Handling
462+==============
463+
464+.. list-table:: Error Handling
465+ :widths: 10 30
466+ :stub-columns: 1
467+
468+ * - tryCatch
469+ - `tryCatch t (\err => t')` will run `t`, and if it fails, roll back the elaboration state and run `t'`,
470+ but with access to the knowledge of why `t` failed.
471+
472+ Signature:
473+
474+ tryCatch : Elab a -> (Err -> Elab a) -> Elab a
475+
476+ Fixme - following does not work.
477+
478+ .. code-block:: idris
479+
480+ %language ElabReflection
481+
482+ id1 : Elab ()
483+ id1 = do
484+ tryCatch (intro `{{x}})
485+ (\err -> (intro `{{x}}))
486+ fill (Var `{{x}})
487+ solve
488+
489+ idNat : Nat -> Nat
490+ idNat = %runElab id1
491+
492+ * - fail
493+ - Halt elaboration with an error
494+
495+ Signature:
496+
497+ fail : List ErrorReportPart -> Elab a
498+
499+ Return type is given by last term so fail cant be at the the last term, we would expect fail to be in some sort of conditional statement:
500+
501+ .. code-block:: idris
502+
503+ %language ElabReflection
504+
505+ id1 : Elab ()
506+ id1 = do
507+ intro `{{x}}
508+ fill (Var `{{x}})
509+ if True
510+ then
511+ fail [TextPart "error message"]
512+ else
513+ solve
514+
515+ idNat : Nat -> Nat
516+ idNat = %runElab id1</td>
517+
docs/proofs/tactics.rstnew file+431
@@ -0,0 +1,431 @@
1+Elaborator Reflection - Tactics
2+===============================
3+
4+The Idris part of the code for elaborator reflection is in
5+Elab.idr `<https://github.com/idris-lang/Idris-dev/blob/master/libs/prelude/Language/Reflection/Elab.idr>`_
6+Before we look at the Elab monad we need to know how to construct terms.
7+
8+Proof State
9+===========
10+
11+Tactics operate on the proof state. The proof state contains various pieces of information, at this stage, the important ones for us are:
12+
13+- A hole queue - This contains a list of the names of the holes used in the proof term. The solution to each hole may depend on the other holes.
14+- A goal type - The type of the term that is under construction for the current goal.
15+- A possibly incomplete proof term, which is being calculated and should be the goal type at the end of elaboration.
16+- Context - A collection of open unification problems, representing recoverable failures of unification that may yet unify once more variables are solved.
17+
18+There are many other pieces of information in the proof state such as the names used , such as the bodies of case blocks that need to be elaborated.but, for now, we will leave the system to handle these.
19+
20+.. image:: image/elabProofState.png
21+ :width: 283px
22+ :height: 232px
23+
24+Names TTName
25+------------
26+
27+Names in an Idris program are evaluated at runtime but sometimes we need a 'variable name' which can be referred to as an unevaluated symbol.
28+The names used in terms have different constructors depending on their type:
29+
30++---------------------------+-----------------------------------------------+
31+| UN String | A user-provided name |
32++---------------------------+-----------------------------------------------+
33+| NS (UN "foo") ["B", "A"]) | A name in some namespace |
34++---------------------------+-----------------------------------------------+
35+| MN Int String | Machine-chosen names |
36++---------------------------+-----------------------------------------------+
37+| SN SpecialName | Special names, to make conflicts impossible |
38+| | and language features predictable |
39++---------------------------+-----------------------------------------------+
40+
41+
42+A user defined name can be constructed like this:
43+
44+.. code-block:: idris
45+
46+ Idris> UN "x"
47+ UN "x" : TTName
48+
49+.. code-block:: idris
50+
51+ Idris> NS (UN "x") ["b","a"]
52+ NS (UN "x") ["b", "a"] : TTName
53+
54+.. list-table:: machine-chosen names
55+
56+ * - A machine-chosen name needs to be generated within an Elab monad (see below for details) and is unique within that monad. This produced: {abc_140}{abc_141} so although gensym "abc" was called twice each one had a different integer:
57+ - example of unique names:
58+
59+ .. code-block:: idris
60+
61+ implementation Show TTName where
62+ show (UN s) = "`{{"++s++"}}"
63+ show (NS t a) = "{"++(show t)++
64+ "."++(show a)++"}"
65+ show (MN i s) = "{"++s++"_"++(show i)++"}"
66+ show (SN sn) = "TTName special name"
67+
68+ showGensym : String
69+ showGensym = %runElab (do
70+ debugMessage [TextPart (
71+ show !(gensym "abc") ++
72+ show !(gensym "abc")
73+ )]
74+ )
75+
76+Quasiquotation
77+==============
78+
79+Since names are used frequently in elaborator reflection there is a shortcut for constructing them:
80+
81+.. list-table:: Quasiquotation
82+
83+ * - An unresolved variable "x" is wrapped in backtick and double braces:
84+ - example
85+
86+ .. code-block:: idris
87+
88+ Idris> `{{x}}
89+ UN "x" : TTName
90+
91+
92+ * - Single braces are used for existing variables:
93+ - example
94+
95+ .. code-block:: idris
96+
97+ Idris> `{x}
98+ No such variable x
99+ Idris> :let x=2
100+ Idris> `{x}
101+ UN "x" : TTName
102+
103+
104+ * - brackets are used for an expression:
105+ - example here type is inferable
106+
107+ .. code-block:: idris
108+
109+ Idris> :let a=2
110+ Idris> `(a)
111+ P Ref (UN "a") (TConst (AType (ATInt ITBig))) : TT
112+
113+
114+ * - Expression with explicit type:
115+ - example
116+
117+ .. code-block:: idris
118+
119+ Idris> `(a:Integer)
120+ P Ref (UN "a") (TConst (AType (ATInt ITBig))) : TT
121+
122+
123+ * - If we want the vale we can escape from quasiquotation by using anti-quotation (tilde)
124+ - example
125+
126+ .. code-block:: idris
127+
128+ Idris> `(~a)
129+ 2 : Integer
130+
131+quasiquotation summary:
132+
133++------------+-----------+----------------------------------------------------------+
134+| |Reification| |
135++============+===========+==========================================================+
136+| \`{{n}} | TTName | Use for new names. Unresolved quotation of the name n. |
137++------------+-----------+----------------------------------------------------------+
138+| \`{n} | TTName | Use for existing names. Resolved quotation of the name |
139+| | | n. n is a reference to a unique name in scope. |
140++------------+-----------+----------------------------------------------------------+
141+| \`(e) | | expression e for which a type is inferable. |
142++------------+-----------+----------------------------------------------------------+
143+| \`(e:t) | | expression e with a given type e. |
144++------------+-----------+----------------------------------------------------------+
145+| ~a | | anti-quotation - sub region which can be evaluated rather|
146+| | | than quoted. |
147++------------+-----------+----------------------------------------------------------+
148+|(Var\`{{x}})| Raw | |
149++------------+-----------+----------------------------------------------------------+
150+
151+TT
152+==
153+
154+There is a notation for a term in TT as it is being constructed (based on a BNF-like grammar), this is used for example in the debug output, it is a compact way to see the state of the term so we use it here.
155+So internally the program is stored as a tree structure using the following syntax:
156+
157++------------+-------+-------------+---------------------------------------------+
158+| | | Syntax | More Information |
159++============+=======+=============+=============================================+
160+| term | | t | |
161++------------+-------+-------------+---------------------------------------------+
162+| binding | | b | |
163++------------+-------+-------------+---------------------------------------------+
164+| constant | t ::= | c | |
165++------------+-------+-------------+---------------------------------------------+
166+| variable | t ::= | x | |
167++------------+-------+-------------+---------------------------------------------+
168+| variable | t ::= | b.t | so a dot '.' tells us this is some sort of |
169+| binding | | | binding. |
170++------------+-------+-------------+---------------------------------------------+
171+| application| t ::= | t t | As with Idris, juxtaposition indicates |
172+| | | | function application. Note: we use the same |
173+| | | | symbol 't' for terms |
174++------------+-------+-------------+---------------------------------------------+
175+| Type | t ::= | T | |
176+| constructor| | | |
177++------------+-------+-------------+---------------------------------------------+
178+| Data | t ::= | C | |
179+| constructor| | | |
180++------------+-------+-------------+---------------------------------------------+
181+| function | b::= | λ c:t | colon ':' separates parameters from body of |
182+| | | | binding. |
183++------------+-------+-------------+---------------------------------------------+
184+| let binding| b::= | let\|-> t:t | |
185++------------+-------+-------------+---------------------------------------------+
186+| function | b::= | ∀ x:t | |
187++------------+-------+-------------+---------------------------------------------+
188+| Type | c::= | \*i | The universe hierarchy is usually handled |
189+| universe | | | automatically so we can just use\* for the |
190+| | | | type of types. |
191++------------+-------+-------------+---------------------------------------------+
192+| integer | c:== | i | |
193+| literal | | | |
194++------------+-------+-------------+---------------------------------------------+
195+|integer type| c:== | Integer | |
196++------------+-------+-------------+---------------------------------------------+
197+| string | c:== | s | |
198+| literal | | | |
199++------------+-------+-------------+---------------------------------------------+
200+| string type| c:== | String | |
201++------------+-------+-------------+---------------------------------------------+
202+|focused hole| | ?x : t | Conor McBride 1999 thesis. |
203++------------+-------+-------------+---------------------------------------------+
204+| guess | | ?x ≈ t : t | Conor McBride 1999 thesis. |
205++------------+-------+-------------+---------------------------------------------+
206+
207+Sometimes the part of the term in focus is underlined.
208+
209+Reflection of the well typed core language
210+
211+.. code-block:: idris
212+
213+ data TT =
214+ ||| A reference to some name (P for Parameter)
215+ P NameType TTName TT |
216+ ||| de Bruijn variables
217+ V Int |
218+ ||| Bind a variable
219+ Bind TTName (Binder TT) TT |
220+ ||| Apply one term to another
221+ App TT TT |
222+ ||| Embed a constant
223+ TConst Const |
224+ ||| Erased terms
225+ Erased |
226+ ||| The type of types along (with universe constraints)
227+ TType TTUExp |
228+ ||| Alternative universes for dealing with uniqueness
229+ UType Universe |
230+
231+TT stores local bound variables using De Bruijn index, when working in Idris this does not concern the user because string names are used for variables. Converting bound variables internally to index values means that the same variable name can be used, in different lambda terms, without ambiguity and without the need for α-substitution.
232+De Bruijn index which is a integer where:
233+
234+- 0=inside current (inner) lambda term
235+- 1= next outer lambda term
236+- 2= next outer and so on
237+
238+Raw
239+---
240+Raw is similar to TT except it is used before types are known. The types should be resolved by the type checker.
241+
242+.. code-block:: idris
243+
244+ data Raw =
245+ ||| Variables, global or local
246+ Var TTName |
247+ ||| Bind a variable
248+ RBind TTName (Binder Raw) Raw |
249+ ||| Application
250+ RApp Raw Raw |
251+ ||| The type of types
252+ RType |
253+ ||| Alternative universes for dealing with uniqueness
254+ RUType Universe |
255+ ||| Embed a constant
256+ RConstant Const |
257+
258+Expression Syntax
259+=================
260+
261+There is a way of notating expressions such as those used in the proof state (example: goal type and proof terms) which is reasonably standard in the papers written about this subject.
262+
263+This notation is not entered directly by metaprogrammers but it is seen, for example in debug output. So this notation is explained here because it is useful to be familiar with it.
264+
265+The notation assumes right-associativity, in the absence of brackets, the term to the right binds more tightly than the one on the left.
266+So, for nested lambda terms:
267+
268++---------------+--------+-------------------+
269+| λ a . λ b . f | means | λ a .( λ b . f) |
270++---------------+--------+-------------------+
271+
272+and the same for function application:
273+
274++---------------+--------+-------------------+
275+| f g x | means | f (g x) |
276++---------------+--------+-------------------+
277+
278+In contrast, in lambda calculus, function application is usually regarded as left-associative,
279+Here are some typical examples of the notation used for expressions:
280+
281++-----------------------+
282+| ? {hole_0} . {hole_0} |
283++-----------------------+
284+
285+The term, to be derived, may start off in this state following something like this:
286+
287+.. code-block:: idris
288+
289+ myScript : Elab ()
290+ myScript= do
291+
292+The dot '.' tells us this is some sort of binding.
293+
294++----------------------------------------------+
295+| ?{hole_0} ≈ ? {hole_2} . {hole_2} . {hole_0} |
296++----------------------------------------------+
297+
298+This is a slightly more complicated example arising from:
299+
300+.. code-block:: idris
301+
302+ idNat : Nat -> Nat
303+ idNat = %runElab (do
304+
305+This introduces a guess that hole_0 = hole_2 .
306+
307++----------------------------------------------------+
308+| ?{hole_0} ≈ λ x . ? {hole_2} . {hole_2} . {hole_0} |
309++----------------------------------------------------+
310+
311+Following on from the previous example a lambda function is introduced like this:
312+
313+.. code-block:: idris
314+
315+ intro `{{x}}
316+
317+So now the expression is wrapped in a lambda binding.
318+
319++-------------------------------------------------------+
320+| ?{hole_0} ≈ λ x . ?{hole_2} ≈ x . {hole_2} . {hole_0} |
321++-------------------------------------------------------+
322+
323+Following on, we can use the fill tactic like this:
324+
325+.. code-block:: idris
326+
327+ fill (Var `{{x}})
328+
329+which introduces another guess.
330+
331++--------------------------------+
332+| ?{hole_0} ≈ λ x . x . {hole_0} |
333++--------------------------------+
334+
335+The solve tactic completes the proof
336+
337+Binders
338+=======
339+
340+Here we look at each tactic in turn to see how they affect the proof state.
341+
342+Introduction tactics for binders. The binder types are:
343+
344+- lambda function (intro)
345+- dependent function (forall)
346+- let (letBind)
347+- pattern (patbind)
348+
349+A precondition of these tactics is that the focused hole is of the form:
350+
351++-----------+
352+| ?h : t.h |
353++-----------+
354+
355+that is, that the body of its scope consists directly of a reference to the hole-bound variable. If a hole binder were of the form:
356+
357++--------------------+
358+| ?h : t1 -> t2.f h |
359++--------------------+
360+
361+and a tactic such as
362+
363++------------------+
364+| intro \`{{x}} |
365++------------------+
366+
367+were applied, the result would be the term
368+
369++---------------------------+
370+| ?h : t2 . λ x:t1. f h |
371++---------------------------+
372+
373+However this would cause the application of f to be ill-typed, as it expects an argument of type t1->t2, not an argument of type t2. Additionally, some binding tactics require that t, the type of the hole h, have a specific form, because the binder to be established may have a typing rule associated with it.
374+
375+.. list-table:: Binders
376+ :widths: 10 30
377+ :stub-columns: 1
378+
379+ * - intro
380+ - Introduce a lambda binding around the current hole and focus on the body.
381+
382+ Requires that the hole be in binding form (use 'attack' if it might not be).
383+
384+ @ n the name to use for the argument.
385+
386+ Signature:
387+
388+ intro : (n : TTName) -> Elab ()
389+
390+ Result
391+
392+ λn:t1.?h:[n/x]t2.h
393+
394+ * - intro'
395+ - Introduce a lambda binding around the current hole and focus on the body, using the name provided by the type of the hole.
396+
397+ Requires that the hole be immediately under its binder (use 'attack' if it might not be).
398+
399+ Signature:
400+
401+ intro' : Elab ()
402+
403+ * - forall
404+ - Introduce a dependent function type binding into the current hole, and focus on the body. Requires that the hole be immediately under its binder
405+
406+ (use 'attack' if it might not be).
407+
408+ Signature:
409+
410+ forall : TTName -> Raw -> Elab ()
411+
412+ * - patbind
413+ - Introduce a new pattern binding. Requires that the hole be immediately under its binder (use 'attack' if it might not be).
414+
415+ Signature:
416+
417+ patbind : TTName -> Elab ()
418+
419+ * - letbind
420+ - Introduce a new let binding.
421+
422+ Requires that the hole be immediately under its binder (use 'attack' if it might not be).
423+
424+ - @ n the name to let bind
425+ - @ ty the type of the term to be let-bound
426+ - @ tm the term to be bound
427+
428+ Signature:
429+
430+ letbind : (n : TTName) -> (ty, tm : Raw) -> Elab ()
431+