| author | wenzelm | 
| Wed, 08 Mar 2023 22:40:15 +0100 | |
| changeset 77592 | 832139c1b268 | 
| parent 70520 | 11d8517d9384 | 
| child 78150 | 2963ea647c2a | 
| permissions | -rw-r--r-- | 
| 
60248
 
f7e4294216d2
updated Eisbach, using version fb741500f533 of its Bitbucket repository;
 
wenzelm 
parents: 
60209 
diff
changeset
 | 
1  | 
(* Title: HOL/Eisbach/Eisbach.thy  | 
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
2  | 
Author: Daniel Matichuk, NICTA/UNSW  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
3  | 
|
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
4  | 
Main entry point for Eisbach proof method language.  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
5  | 
*)  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
6  | 
|
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
7  | 
theory Eisbach  | 
| 
62134
 
2405ab06d5b1
remove Eisbach's dependency on HOL
 
matichuk <daniel.matichuk@nicta.com.au> 
parents: 
61918 
diff
changeset
 | 
8  | 
imports Pure  | 
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
9  | 
keywords  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
10  | 
"method" :: thy_decl and  | 
| 
60209
 
022ca2799c73
updated Eisbach, using version 5df3d8c72403 of its Bitbucket repository;
 
wenzelm 
parents: 
60119 
diff
changeset
 | 
11  | 
"conclusion"  | 
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
12  | 
"declares"  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
13  | 
"methods"  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
14  | 
"\<bar>" "\<Rightarrow>"  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
15  | 
"uses"  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
16  | 
begin  | 
| 
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
17  | 
|
| 69605 | 18  | 
ML_file \<open>parse_tools.ML\<close>  | 
19  | 
ML_file \<open>method_closure.ML\<close>  | 
|
20  | 
ML_file \<open>eisbach_rule_insts.ML\<close>  | 
|
21  | 
ML_file \<open>match_method.ML\<close>  | 
|
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
22  | 
|
| 
67899
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
23  | 
|
| 
60209
 
022ca2799c73
updated Eisbach, using version 5df3d8c72403 of its Bitbucket repository;
 
wenzelm 
parents: 
60119 
diff
changeset
 | 
24  | 
method solves methods m = (m; fail)  | 
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
25  | 
|
| 
67899
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
26  | 
method repeat_new methods m = (m ; (repeat_new \<open>m\<close>)?)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
27  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
28  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
29  | 
section \<open>Debugging methods\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
30  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
31  | 
method_setup print_raw_goal = \<open>Scan.succeed (fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
32  | 
(fn (ctxt, st) => (  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
33  | 
Output.writeln (Thm.string_of_thm ctxt st);  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
34  | 
Seq.make_results (Seq.single (ctxt, st)))))\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
35  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
36  | 
method_setup print_headgoal =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
37  | 
\<open>Scan.succeed (fn ctxt => fn _ => fn (ctxt', thm) =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
38  | 
((SUBGOAL (fn (t,_) =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
39  | 
(Output.writeln  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
40  | 
(Pretty.string_of (Syntax.pretty_term ctxt t)); all_tac)) 1 thm);  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
41  | 
(Seq.make_results (Seq.single (ctxt', thm)))))\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
42  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
43  | 
ML \<open>fun method_evaluate text ctxt facts =  | 
| 70520 | 44  | 
NO_CONTEXT_TACTIC ctxt  | 
| 
67899
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
45  | 
(Method.evaluate_runtime text ctxt facts)\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
46  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
47  | 
method_setup timeit =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
48  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
49  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
50  | 
fun timed_tac st seq = Seq.make (fn () => Option.map (apsnd (timed_tac st))  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
51  | 
(timeit (fn () => (Seq.pull seq))));  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
52  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
53  | 
fun tac st' =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
54  | 
timed_tac st' (method_evaluate m ctxt facts st');  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
55  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
56  | 
in SIMPLE_METHOD tac [] end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
57  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
58  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
59  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
60  | 
section \<open>Simple Combinators\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
61  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
62  | 
method_setup defer_tac = \<open>Scan.succeed (fn _ => SIMPLE_METHOD (defer_tac 1))\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
63  | 
method_setup prefer_last = \<open>Scan.succeed (fn _ => SIMPLE_METHOD (PRIMITIVE (Thm.permute_prems 0 ~1)))\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
64  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
65  | 
method_setup all =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
66  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
67  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
68  | 
fun tac i st' =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
69  | 
Goal.restrict i 1 st'  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
70  | 
|> method_evaluate m ctxt facts  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
71  | 
|> Seq.map (Goal.unrestrict i)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
72  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
73  | 
in SIMPLE_METHOD (ALLGOALS tac) facts end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
74  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
75  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
76  | 
method_setup determ =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
77  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
78  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
79  | 
fun tac st' = method_evaluate m ctxt facts st'  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
80  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
81  | 
in SIMPLE_METHOD (DETERM tac) facts end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
82  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
83  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
84  | 
method_setup changed =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
85  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
86  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
87  | 
fun tac st' = method_evaluate m ctxt facts st'  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
88  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
89  | 
in SIMPLE_METHOD (CHANGED tac) facts end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
90  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
91  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
92  | 
|
| 69272 | 93  | 
text \<open>The following \<open>fails\<close> and \<open>succeeds\<close> methods protect the goal from the effect  | 
| 
67899
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
94  | 
of a method, instead simply determining whether or not it can be applied to the current goal.  | 
| 69272 | 95  | 
The \<open>fails\<close> method inverts success, only succeeding if the given method would fail.\<close>  | 
| 
67899
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
96  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
97  | 
method_setup fails =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
98  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
99  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
100  | 
fun fail_tac st' =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
101  | 
(case Seq.pull (method_evaluate m ctxt facts st') of  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
102  | 
SOME _ => Seq.empty  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
103  | 
| NONE => Seq.single st')  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
104  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
105  | 
in SIMPLE_METHOD fail_tac facts end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
106  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
107  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
108  | 
method_setup succeeds =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
109  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
110  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
111  | 
fun can_tac st' =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
112  | 
(case Seq.pull (method_evaluate m ctxt facts st') of  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
113  | 
SOME (st'',_) => Seq.single st'  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
114  | 
| NONE => Seq.empty)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
115  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
116  | 
in SIMPLE_METHOD can_tac facts end)  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
117  | 
\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
118  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
119  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
120  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
121  | 
text \<open>Finding a goal based on successful application of a method\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
122  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
123  | 
method_setup find_goal =  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
124  | 
\<open>Method.text_closure >> (fn m => fn ctxt => fn facts =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
125  | 
let  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
126  | 
fun prefer_first i = SELECT_GOAL  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
127  | 
(fn st' =>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
128  | 
(case Seq.pull (method_evaluate m ctxt facts st') of  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
129  | 
SOME (st'',_) => Seq.single st''  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
130  | 
| NONE => Seq.empty)) i THEN prefer_tac i  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
131  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
132  | 
in SIMPLE_METHOD (FIRSTGOAL prefer_first) facts end)\<close>  | 
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
133  | 
|
| 
 
730fa992da38
additional Eisbach combinators and utility methods
 
kleing 
parents: 
63527 
diff
changeset
 | 
134  | 
|
| 
60119
 
54bea620e54f
added Eisbach, using version 3752768caa17 of its Bitbucket repository;
 
wenzelm 
parents:  
diff
changeset
 | 
135  | 
end  |