944 %Interestingly, in case of \isacommand{bind\_set} |
944 %Interestingly, in case of \isacommand{bind\_set} |
945 %and \isacommand{bind\_res} the binding clauses above will make a difference to the semantics |
945 %and \isacommand{bind\_res} the binding clauses above will make a difference to the semantics |
946 %of the specifications (the corresponding $\alpha$-equivalence will differ). We will |
946 %of the specifications (the corresponding $\alpha$-equivalence will differ). We will |
947 %show this later with an example. |
947 %show this later with an example. |
948 |
948 |
949 There are also some restrictions we need to impose on binding clauses: the |
949 There are also some restrictions we need to impose on binding clauses. The |
950 main idea behind these restrictions is that we obtain a sensible notion of |
950 main idea behind these restrictions is that we obtain a sensible notion of |
951 $\alpha$-equivalence where it is ensured that within a given scope a |
951 $\alpha$-equivalence where it is ensured that within a given scope a |
952 variable occurence cannot be bound and free at the same time. First, a body can only occur in |
952 variable occurence cannot be both bound and free at the same time. The first |
|
953 restriction is that a body can only occur in |
953 \emph{one} binding clause of a term constructor (this ensures that the bound |
954 \emph{one} binding clause of a term constructor (this ensures that the bound |
954 variables of a body cannot be free at the same time by specifying an |
955 variables of a body cannot be free at the same time by specifying an |
955 alternative binder for the body). For binders we distinguish between |
956 alternative binder for the same body). For binders we distinguish between |
956 \emph{shallow} and \emph{deep} binders. Shallow binders are just |
957 \emph{shallow} and \emph{deep} binders. Shallow binders are just |
957 labels. The restriction we need to impose on them is that in case of |
958 labels. The restriction we need to impose on them is that in case of |
958 \isacommand{bind\_set} and \isacommand{bind\_res} the labels must either |
959 \isacommand{bind\_set} and \isacommand{bind\_res} the labels must either |
959 refer to atom types or to sets of atom types; in case of \isacommand{bind} |
960 refer to atom types or to sets of atom types; in case of \isacommand{bind} |
960 the labels must refer to atom types or lists of atom types. Two examples for |
961 the labels must refer to atom types or lists of atom types. Two examples for |
1166 |
1167 |
1167 The resulting datatype definition is legal in Isabelle/HOL provided the datatypes are |
1168 The resulting datatype definition is legal in Isabelle/HOL provided the datatypes are |
1168 non-empty and the types in the constructors only occur in positive |
1169 non-empty and the types in the constructors only occur in positive |
1169 position (see \cite{Berghofer99} for an indepth description of the datatype package |
1170 position (see \cite{Berghofer99} for an indepth description of the datatype package |
1170 in Isabelle/HOL). We then define the user-specified binding |
1171 in Isabelle/HOL). We then define the user-specified binding |
1171 functions, called @{term "bn"}, by recursion over the corresponding |
1172 functions @{term "bn"} by recursion over the corresponding |
1172 raw datatype. We can also easily define permutation operations by |
1173 raw datatype. We can also easily define permutation operations by |
1173 recursion so that for each term constructor @{text "C"} with the |
1174 recursion so that for each term constructor @{text "C"} with |
1174 argument types @{text "ty"}$_{1..n}$ we have that |
1175 arguments @{text "z"}$_{1..n}$ we have that |
1175 % |
1176 % |
1176 \begin{equation}\label{ceqvt} |
1177 \begin{equation}\label{ceqvt} |
1177 @{text "p \<bullet> (C z\<^isub>1 \<dots> z\<^isub>n) = C (p \<bullet> z\<^isub>1) \<dots> (p \<bullet> z\<^isub>n)"} |
1178 @{text "p \<bullet> (C z\<^isub>1 \<dots> z\<^isub>n) = C (p \<bullet> z\<^isub>1) \<dots> (p \<bullet> z\<^isub>n)"} |
1178 \end{equation} |
1179 \end{equation} |
1179 |
1180 |
1180 \noindent |
|
1181 where the variables @{text "z"}$_{1..n}$ are of types @{text "ty"}$_{1..n}$. |
|
1182 |
|
1183 The first non-trivial step we have to perform is the generation of |
1181 The first non-trivial step we have to perform is the generation of |
1184 free-variable functions from the specifications. Given a raw term, these |
1182 free-variable functions from the specifications. For the |
1185 functions return sets of atoms. Assuming a nominal datatype |
1183 \emph{raw} types @{text "ty"}$_{1..n}$ of a specification, |
1186 specification as in \eqref{scheme} and its \emph{raw} types @{text "ty"}$_{1..n}$, |
|
1187 we define the free-variable functions |
1184 we define the free-variable functions |
1188 % |
1185 % |
1189 \begin{equation}\label{fvars} |
1186 \begin{equation}\label{fvars} |
1190 @{text "fv_ty\<^isub>1, \<dots>, fv_ty\<^isub>n"} |
1187 @{text "fv_ty\<^isub>1, \<dots>, fv_ty\<^isub>n"} |
1191 \end{equation} |
1188 \end{equation} |
1204 bound, as we saw in the example with ``plain'' @{text Let}s. We need therefore a function |
1201 bound, as we saw in the example with ``plain'' @{text Let}s. We need therefore a function |
1205 that calculates those unbound atoms in a deep binder. |
1202 that calculates those unbound atoms in a deep binder. |
1206 |
1203 |
1207 While the idea behind these free-variable functions is clear (they just |
1204 While the idea behind these free-variable functions is clear (they just |
1208 collect all atoms that are not bound), because of our rather complicated |
1205 collect all atoms that are not bound), because of our rather complicated |
1209 binding mechanisms their definitions are somewhat involved. Given a |
1206 binding mechanisms their definitions are somewhat involved. The functions |
1210 term-constructor @{text "C"} of type @{text ty} and some associated binding |
1207 are defined by recursion defining a clause for each term-constructor. Given |
1211 clauses @{text "bc\<^isub>1\<dots>bc\<^isub>k"}, the result of the @{text "fv_ty (C z\<^isub>1 \<dots> z\<^isub>n)"} will be |
1208 the term-constructor @{text "C"} of type @{text ty} and some associated |
1212 the union @{text "fv(bc\<^isub>1) \<union> \<dots> \<union> fv(bc\<^isub>k)"} of free variables calculated for |
1209 binding clauses @{text "bc\<^isub>1\<dots>bc\<^isub>k"}, the result of @{text |
1213 each binding clause. Given a binding clause @{text bc} is of the form |
1210 "fv_ty (C z\<^isub>1 \<dots> z\<^isub>n)"} will be the union @{text |
|
1211 "fv(bc\<^isub>1) \<union> \<dots> \<union> fv(bc\<^isub>k)"}. Given the binding clause @{text |
|
1212 bc\<^isub>i} is of the form |
1214 % |
1213 % |
1215 \begin{equation} |
1214 \begin{equation} |
1216 \mbox{\isacommand{bind} @{text "b\<^isub>1\<dots>b\<^isub>p"} \isacommand{in} @{text "d\<^isub>1\<dots>d\<^isub>q"}} |
1215 \mbox{\isacommand{bind\_set} @{text "b\<^isub>1\<dots>b\<^isub>p"} \isacommand{in} @{text "d\<^isub>1\<dots>d\<^isub>q"}} |
1217 \end{equation} |
1216 \end{equation} |
1218 |
1217 |
1219 \noindent |
1218 \noindent |
1220 where the body labels @{text "d"}$_{1..q}$ refer to types @{text ty}$_{1..q}$; the binders |
1219 in which the body-labels @{text "d"}$_{1..q}$ refer to types @{text ty}$_{1..q}$, |
1221 @{text b}$_{1..p}$ |
1220 and the binders @{text b}$_{1..p}$ |
1222 either refer to labels of atom types (in case of shallow binders) or to binding |
1221 either refer to labels of atom types (in case of shallow binders) or to binding |
1223 functions taking a single label as argument (in case of deep binders). Assuming the |
1222 functions taking a single label as argument (in case of deep binders). Assuming the |
1224 free variables of the bodies is the set @{text "D"}, the bound variables of the binders |
1223 set @{text "D"} stands for the free atoms in the bodies, @{text B} for the |
1225 is the set @{text B} and the free variables of the non-recursive deep binders is @{text "B'"} |
1224 binding atoms in the binders and @{text "B'"} for the free atoms in |
1226 then the free variables of the binding clause @{text bc} is |
1225 non-recursive deep binders, |
1227 % |
1226 then the free atoms of the binding clause @{text bc\<^isub>i} are given by |
1228 \begin{center} |
1227 % |
1229 @{text "fv(bc) = (D - B) \<union> B'"} |
1228 \begin{center} |
1230 \end{center} |
1229 @{text "fv(bc\<^isub>i) \<equiv> (D - B) \<union> B'"} |
1231 |
1230 \end{center} |
1232 \noindent |
1231 |
1233 Formally the set @{text D} is the union of the free variables for the bodies |
1232 \noindent |
1234 % |
1233 The set @{text D} is defined as |
1235 \begin{center} |
1234 % |
1236 @{text "D = fv_ty\<^isub>1 d\<^isub>1 \<union> ... \<union> fv_ty\<^isub>q d\<^isub>q"} |
1235 \begin{center} |
|
1236 @{text "D \<equiv> fv_ty\<^isub>1 d\<^isub>1 \<union> ... \<union> fv_ty\<^isub>q d\<^isub>q"} |
1237 \end{center} |
1237 \end{center} |
1238 |
1238 |
1239 \noindent |
1239 \noindent |
1240 whereby the free variable functions @{text "fv_ty\<^isub>i"} are the ones in \eqref{fvars} |
1240 whereby the functions @{text "fv_ty\<^isub>i"} are the ones we are defining by recursion |
1241 provided the @{text "d\<^isub>i"} refers to one of the types @{text "ty"}$_{1..n}$; |
1241 (see \eqref{fvars}) provided the @{text "d\<^isub>i"} refers to one of the types |
1242 otherwise we set @{text "fv_ty\<^isub>i d\<^isub>i = supp d\<^isub>i"}. |
1242 @{text "ty"}$_{1..n}$; otherwise we set @{text "fv_ty\<^isub>i d\<^isub>i = supp d\<^isub>i"}. |
1243 |
1243 In order to define the set @{text B} we use the following auxiliary bn-functions |
1244 |
1244 for atom types to which shallow binders have to refer |
1245 if @{text "d\<^isub>i"} is a label |
1245 % |
1246 for an atomic type we use the following auxiliary free variable functions |
|
1247 |
|
1248 \begin{center} |
1246 \begin{center} |
1249 \begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l} |
1247 \begin{tabular}{r@ {\hspace{2mm}}c@ {\hspace{2mm}}l} |
1250 @{text "fv_atom a"} & @{text "="} & @{text "{atom a}"}\\ |
1248 @{text "bn_atom a"} & @{text "="} & @{text "{atom a}"}\\ |
1251 @{text "fv_atom_set as"} & @{text "="} & @{text "atoms as"}\\ |
1249 @{text "bn_atom_set as"} & @{text "="} & @{text "atoms as"}\\ |
1252 @{text "fv_atom_list as"} & @{text "="} & @{text "atoms (set as)"}\\ |
1250 @{text "bn_atom_list as"} & @{text "="} & @{text "atoms (set as)"} |
1253 \end{tabular} |
1251 \end{tabular} |
1254 \end{center} |
1252 \end{center} |
1255 |
1253 |
1256 \noindent |
1254 \noindent |
1257 In these functions, @{text "atoms"}, like @{text "atom"}, coerces |
1255 In these functions, @{text "atoms"}, like @{text "atom"}, coerces |
1258 the set of atoms to a set of the generic atom type. |
1256 the set of atoms to a set of the generic atom type. It is defined as |
1259 It is defined as @{text "atoms as \<equiv> {atom a | a \<in> as}"}. Otherwise |
1257 @{text "atoms as \<equiv> {atom a | a \<in> as}"}. |
1260 |
1258 The set @{text B} is then defined as |
1261 |
1259 % |
1262 |
1260 \begin{center} |
1263 the values, @{text v}, calculated by the rules for each bining clause: |
1261 @{text "B \<equiv> bn_ty\<^isub>1 b\<^isub>1 \<union> ... \<union> bn_ty\<^isub>p b\<^isub>p"} |
1264 % |
1262 \end{center} |
1265 \begin{equation}\label{deepbinderA} |
1263 |
1266 \mbox{% |
1264 \noindent |
1267 \begin{tabular}{c@ {\hspace{2mm}}p{7.4cm}} |
1265 The set @{text "B'"} collects all free atoms in non-recursive deep |
1268 \multicolumn{2}{@ {}l}{\isacommand{bind}~@{term "{}"}~\isacommand{in}~@{text "y"}:}\\ |
1266 binders. Lets assume these binders in @{text "bc\<^isub>i"} are |
1269 $\bullet$ & @{term "v = fv_ty y"} provided @{text "y"} is of type @{text "ty"}\smallskip\\ |
1267 % |
1270 % |
1268 \begin{center} |
1271 \multicolumn{2}{@ {}l}{\isacommand{bind}~@{text "x\<^isub>1\<dots>x\<^isub>n"}~\isacommand{in}~@{text "y\<^isub>1\<dots>y\<^isub>m"}:}\\ |
1269 @{text "bn\<^isub>1 a\<^isub>1, \<dots>, bn\<^isub>r a\<^isub>r"} |
1272 $\bullet$ & @{text "v = (fv_ty\<^isub>1 y\<^isub>1 \<union> .. \<union> fv_ty\<^isub>m y\<^isub>m)"}\\ |
1270 \end{center} |
1273 & \hspace{15mm}@{text "- (fv_aty\<^isub>1 x\<^isub>1 \<union> .. \<union> fv_aty\<^isub>n x\<^isub>n)"}\\ |
1271 |
1274 & provided the bodies @{text "y"}$_{1..m}$ are of type @{text "ty"}$_{1..m}$ and the |
1272 \noindent |
1275 binders @{text "x"}$_{1..n}$ of atomic types @{text "aty"}$_{1..n}$\smallskip\\ |
1273 with none of the @{text "a"}$_{1..r}$ being among the bodies @{text |
1276 \end{tabular}} |
1274 "d"}$_{1..q}$. The set @{text "B'"} is then defined as |
1277 \end{equation} |
1275 % |
1278 \begin{equation}\label{deepbinderB} |
1276 \begin{center} |
1279 \mbox{% |
1277 @{text "B' \<equiv> fv_bn\<^isub>1 a\<^isub>1 \<union> ... \<union> fv_bn\<^isub>r a\<^isub>r"} |
1280 \begin{tabular}{c@ {\hspace{2mm}}p{7.4cm}} |
1278 \end{center} |
1281 \multicolumn{2}{@ {}l}{\isacommand{bind}~@{text "bn x"}~\isacommand{in}~@{text "y\<^isub>1\<dots>y\<^isub>m"}:}\\ |
1279 |
1282 $\bullet$ & @{text "v = (fv_ty\<^isub>1 y\<^isub>1 \<union> .. \<union> fv_ty\<^isub>m y\<^isub>m) - set (bn x) \<union> (fv_bn x)"}\\ |
1280 \noindent |
1283 $\bullet$ & @{text "v = (fv_ty\<^isub>1 y\<^isub>1 \<union> .. \<union> fv_ty\<^isub>m y\<^isub>m) - set (bn x)"}\\ |
1281 Similarly for the other binding modes. |
1284 & provided the @{text "y"}$_{1..m}$ are of type @{text "ty"}$_{1..m}$; the first |
1282 |
1285 clause applies for @{text x} being a non-recursive deep binder (that is |
1283 Note that for non-recursive deep binders, we have to add all atoms that are left |
1286 @{text "x \<noteq> y"}$_{1..m}$), the second for a recursive deep binder |
1284 unbound by the binding function @{text "bn"}. This is the purpose of the functions |
1287 \end{tabular}} |
1285 @{text "fv_bn"}, also defined by recursion. Assume the user has specified |
1288 \end{equation} |
1286 a @{text bn}-clause of the form |
1289 |
1287 % |
1290 \noindent |
1288 \begin{center} |
1291 Similarly for the other binding modes. Note that in a non-recursive deep |
1289 @{text "bn (C z\<^isub>1 \<dots> z\<^isub>n) = rhs"} |
1292 binder, we have to add all atoms that are left unbound by the binding |
1290 \end{center} |
1293 function @{text "bn"}. For this we define the function @{text "fv_bn"}. Assume |
1291 |
1294 for the constructor @{text "C"} the binding function is of the form @{text |
1292 \noindent |
1295 "bn (C z\<^isub>1 \<dots> z\<^isub>n) = rhs"}. We again define a value |
1293 where the @{text "z"}$_{1..n}$ are of types @{text "ty"}$_{1..n}$. For each of |
1296 @{text v} which is exactly as in \eqref{deepbinderA}/\eqref{deepbinderB} for shallow and deep |
1294 the arguments we calculate the free atoms as follows |
1297 binding clauses, except for empty binding clauses are defined as follows: |
1295 % |
1298 % |
1296 \begin{center} |
1299 \begin{equation}\label{bnemptybinder} |
|
1300 \mbox{% |
|
1301 \begin{tabular}{c@ {\hspace{2mm}}p{7cm}} |
1297 \begin{tabular}{c@ {\hspace{2mm}}p{7cm}} |
1302 \multicolumn{2}{@ {}l}{\isacommand{bind}~@{term "{}"}~\isacommand{in}~@{text "y"}:}\\ |
1298 $\bullet$ & @{term "fv_ty\<^isub>i z\<^isub>i"} provided @{text "z\<^isub>i"} does not occur in @{text "rhs"}\\ |
1303 $\bullet$ & @{term "v = fv_ty y"} provided @{text "y"} does not occur in @{text "rhs"} |
1299 $\bullet$ & @{term "fv_bn\<^isub>i z\<^isub>i"} provided @{text "z\<^isub>i"} occurs in @{text "rhs"} |
1304 and the free-variable function for the type of @{text "y"} is @{text "fv_ty"}\\ |
1300 with the recursive call @{text "bn\<^isub>i z\<^isub>i"}\\ |
1305 $\bullet$ & @{term "v = fv_bn y"} provided @{text "y"} occurs in @{text "rhs"} |
1301 $\bullet$ & @{term "{}"} provided @{text "z\<^isub>i"} occurs in @{text "rhs"}, |
1306 with a recursive call @{text "bn y"}\\ |
1302 but without a recursive call |
1307 $\bullet$ & @{term "v = {}"} provided @{text "y"} occurs in @{text "rhs"}, |
1303 \end{tabular} |
1308 but without a recursive call\\ |
1304 \end{center} |
1309 \end{tabular}} |
1305 |
1310 \end{equation} |
1306 \noindent |
1311 |
1307 For defining @{text "fv_bn (C z\<^isub>1 \<dots> z\<^isub>n)"}, we just union up all these values. |
1312 \noindent |
1308 |
1313 The reason why we only have to treat the empty binding clauses specially in |
|
1314 the definition of @{text "fv_bn"} is that binding functions can only use arguments |
|
1315 that do not occur in binding clauses. Otherwise the @{text "bn"} function cannot |
|
1316 be lifted to $\alpha$-equated terms. |
|
1317 |
|
1318 |
|
1319 To see how these definitions work in practice, let us reconsider the term-constructors |
1309 To see how these definitions work in practice, let us reconsider the term-constructors |
1320 @{text "Let"} and @{text "Let_rec"} from the example shown in \eqref{letrecs}. |
1310 @{text "Let"} and @{text "Let_rec"} from the example shown in \eqref{letrecs}. |
1321 For this specification we need to define three free-variable functions, namely |
1311 For them we consider three free-variable functions, namely |
1322 @{text "fv\<^bsub>trm\<^esub>"}, @{text "fv\<^bsub>assn\<^esub>"} and @{text "fv\<^bsub>bn\<^esub>"}. They are as follows: |
1312 @{text "fv\<^bsub>trm\<^esub>"}, @{text "fv\<^bsub>assn\<^esub>"} and @{text "fv\<^bsub>bn\<^esub>"}: |
1323 % |
1313 % |
1324 \begin{center} |
1314 \begin{center} |
1325 \begin{tabular}{@ {}l@ {\hspace{1mm}}c@ {\hspace{1mm}}l@ {}} |
1315 \begin{tabular}{@ {}l@ {\hspace{1mm}}c@ {\hspace{1mm}}l@ {}} |
1326 @{text "fv\<^bsub>trm\<^esub> (Let as t)"} & @{text "="} & @{text "(fv\<^bsub>trm\<^esub> t - set (bn as)) \<union> fv\<^bsub>bn\<^esub> as"}\\ |
1316 @{text "fv\<^bsub>trm\<^esub> (Let as t)"} & @{text "="} & @{text "(fv\<^bsub>trm\<^esub> t - set (bn as)) \<union> fv\<^bsub>bn\<^esub> as"}\\ |
1327 @{text "fv\<^bsub>trm\<^esub> (Let_rec as t)"} & @{text "="} & @{text "(fv\<^bsub>assn\<^esub> as \<union> fv\<^bsub>trm\<^esub> t) - set (bn as)"}\\[1mm] |
1317 @{text "fv\<^bsub>trm\<^esub> (Let_rec as t)"} & @{text "="} & @{text "(fv\<^bsub>assn\<^esub> as \<union> fv\<^bsub>trm\<^esub> t) - set (bn as)"}\\[1mm] |
2058 @{text "Foo\<^isub>2 {a, b} (a, b) (a, b)"} & $=$ & |
2051 @{text "Foo\<^isub>2 {a, b} (a, b) (a, b)"} & $=$ & |
2059 @{text "Foo\<^isub>2 {a, b} (a, b) (b, a)"}\\ |
2052 @{text "Foo\<^isub>2 {a, b} (a, b) (b, a)"}\\ |
2060 \end{tabular} |
2053 \end{tabular} |
2061 \end{center} |
2054 \end{center} |
2062 |
2055 |
2063 To see this, consider the following equations |
|
2064 |
|
2065 \begin{center} |
|
2066 \begin{tabular}{c} |
|
2067 @{term "Abs_print [a,b] (a, b) = Abs_print [a,b] (b, a)"}\\ |
|
2068 @{term "Abs_print [a,b] (a, b) = Abs_print [a,b] (a, b)"}\\ |
|
2069 \end{tabular} |
|
2070 \end{center} |
|
2071 |
|
2072 \noindent |
|
2073 The interesting point is that they do not imply |
|
2074 |
|
2075 \begin{center} |
|
2076 \begin{tabular}{c} |
|
2077 @{term "Abs_print [a,b] ((a, b), (a, b)) = Abs_print [a,b] ((a, b), (b, a))"}\\ |
|
2078 \end{tabular} |
|
2079 \end{center} |
|
2080 |
|
2081 Because of how we set up our definitions, we had to impose restrictions, |
2056 Because of how we set up our definitions, we had to impose restrictions, |
2082 like a single binding function for a deep binder, that are not present in Ott. Our |
2057 like a single binding function for a deep binder, that are not present in Ott. Our |
2083 expectation is that we can still cover many interesting term-calculi from |
2058 expectation is that we can still cover many interesting term-calculi from |
2084 programming language research, for example Core-Haskell. For providing support |
2059 programming language research, for example Core-Haskell. For providing support |
2085 of neat features in Ott, such as subgrammars, the existing datatype |
2060 of neat features in Ott, such as subgrammars, the existing datatype |