src/HOL/Library/Nested_Environment.thy
changeset 10943 3a610d34eb9e
child 10948 1bd100c82300
equal deleted inserted replaced
10942:6bbc41330b68 10943:3a610d34eb9e
       
     1 (*  Title:      HOL/Library/Nested_Environment.thy
       
     2     ID:         $Id$
       
     3     Author:     Markus Wenzel, TU Muenchen
       
     4     License:    GPL (GNU GENERAL PUBLIC LICENSE)
       
     5 *)
       
     6 
       
     7 header {*
       
     8   \title{Nested environments}
       
     9   \author{Markus Wenzel}
       
    10 *}
       
    11 
       
    12 theory Nested_Environment = Main:
       
    13 
       
    14 text {*
       
    15   Consider a partial function @{term [source] "e :: 'a => 'b option"};
       
    16   this may be understood as an \emph{environment} mapping indexes
       
    17   @{typ 'a} to optional entry values @{typ 'b} (cf.\ the basic theory
       
    18   @{text
       
    19   Map}\footnote{\url{http://isabelle.in.tum.de/library/HOL/Map.html}}
       
    20   of Isabelle/HOL).  This basic idea is easily generalized to that of
       
    21   a \emph{nested environment}, where entries may be either basic
       
    22   values or again proper environments.  Then each entry is accessed by
       
    23   a \emph{path}, i.e.\ a list of indexes leading to its position
       
    24   within the structure.
       
    25 *}
       
    26 
       
    27 datatype ('a, 'b, 'c) env =
       
    28     Val 'a
       
    29   | Env 'b  "'c => ('a, 'b, 'c) env option"
       
    30 
       
    31 text {*
       
    32   \medskip In the type @{typ "('a, 'b, 'c) env"} the parameter @{typ
       
    33   'a} refers to basic values (occurring in terminal positions), type
       
    34   @{typ 'b} to values associated with proper (inner) environments, and
       
    35   type @{typ 'c} with the index type for branching.  Note that there
       
    36   is no restriction on any of these types.  In particular, arbitrary
       
    37   branching may yield rather large (transfinite) tree structures.
       
    38 *}
       
    39 
       
    40 
       
    41 subsection {* The lookup operation *}
       
    42 
       
    43 text {*
       
    44   Lookup in nested environments works by following a given path of
       
    45   index elements, leading to an optional result (a terminal value or
       
    46   nested environment).  A \emph{defined position} within a nested
       
    47   environment is one where @{term lookup} at its path does not yield
       
    48   @{term None}.
       
    49 *}
       
    50 
       
    51 consts
       
    52   lookup :: "('a, 'b, 'c) env => 'c list => ('a, 'b, 'c) env option"
       
    53   lookup_option :: "('a, 'b, 'c) env option => 'c list => ('a, 'b, 'c) env option"
       
    54 
       
    55 primrec (lookup)
       
    56   "lookup (Val a) xs = (if xs = [] then Some (Val a) else None)"
       
    57   "lookup (Env b es) xs =
       
    58     (case xs of
       
    59       [] => Some (Env b es)
       
    60     | y # ys => lookup_option (es y) ys)"
       
    61   "lookup_option None xs = None"
       
    62   "lookup_option (Some e) xs = lookup e xs"
       
    63 
       
    64 hide const lookup_option
       
    65 
       
    66 text {*
       
    67   \medskip The characteristic cases of @{term lookup} are expressed by
       
    68   the following equalities.
       
    69 *}
       
    70 
       
    71 theorem lookup_nil: "lookup e [] = Some e"
       
    72   by (cases e) simp_all
       
    73 
       
    74 theorem lookup_val_cons: "lookup (Val a) (x # xs) = None"
       
    75   by simp
       
    76 
       
    77 theorem lookup_env_cons:
       
    78   "lookup (Env b es) (x # xs) =
       
    79     (case es x of
       
    80       None => None
       
    81     | Some e => lookup e xs)"
       
    82   by (cases "es x") simp_all
       
    83 
       
    84 lemmas lookup.simps [simp del]
       
    85   and lookup_simps [simp] = lookup_nil lookup_val_cons lookup_env_cons
       
    86 
       
    87 theorem lookup_eq:
       
    88   "lookup env xs =
       
    89     (case xs of
       
    90       [] => Some env
       
    91     | x # xs =>
       
    92       (case env of
       
    93         Val a => None
       
    94       | Env b es =>
       
    95           (case es x of
       
    96             None => None
       
    97           | Some e => lookup e xs)))"
       
    98   by (simp split: list.split env.split)
       
    99 
       
   100 text {*
       
   101   \medskip Displaced @{term lookup} operations, relative to a certain
       
   102   base path prefix, may be reduced as follows.  There are two cases,
       
   103   depending whether the environment actually extends far enough to
       
   104   follow the base path.
       
   105 *}
       
   106 
       
   107 theorem lookup_append_none:
       
   108   "!!env. lookup env xs = None ==> lookup env (xs @ ys) = None"
       
   109   (is "PROP ?P xs")
       
   110 proof (induct xs)
       
   111   fix env :: "('a, 'b, 'c) env"
       
   112   {
       
   113     assume "lookup env [] = None"
       
   114     hence False by simp
       
   115     thus "lookup env ([] @ ys) = None" ..
       
   116   next
       
   117     fix x xs
       
   118     assume hyp: "PROP ?P xs"
       
   119     assume asm: "lookup env (x # xs) = None"
       
   120     show "lookup env ((x # xs) @ ys) = None"
       
   121     proof (cases env)
       
   122       case Val
       
   123       thus ?thesis by simp
       
   124     next
       
   125       fix b es assume env: "env = Env b es"
       
   126       show ?thesis
       
   127       proof (cases "es x")
       
   128         assume "es x = None"
       
   129         with env show ?thesis by simp
       
   130       next
       
   131         fix e assume es: "es x = Some e"
       
   132         show ?thesis
       
   133         proof (cases "lookup e xs")
       
   134           case None
       
   135           hence "lookup e (xs @ ys) = None" by (rule hyp)
       
   136           with env es show ?thesis by simp
       
   137         next
       
   138           case Some
       
   139           with asm env es have False by simp
       
   140           thus ?thesis ..
       
   141         qed
       
   142       qed
       
   143     qed
       
   144   }
       
   145 qed
       
   146 
       
   147 theorem lookup_append_some:
       
   148   "!!env e. lookup env xs = Some e ==> lookup env (xs @ ys) = lookup e ys"
       
   149   (is "PROP ?P xs")
       
   150 proof (induct xs)
       
   151   fix env e :: "('a, 'b, 'c) env"
       
   152   {
       
   153     assume "lookup env [] = Some e"
       
   154     hence "env = e" by simp
       
   155     thus "lookup env ([] @ ys) = lookup e ys" by simp
       
   156   next
       
   157     fix x xs
       
   158     assume hyp: "PROP ?P xs"
       
   159     assume asm: "lookup env (x # xs) = Some e"
       
   160     show "lookup env ((x # xs) @ ys) = lookup e ys"
       
   161     proof (cases env)
       
   162       fix a assume "env = Val a"
       
   163       with asm have False by simp
       
   164       thus ?thesis ..
       
   165     next
       
   166       fix b es assume env: "env = Env b es"
       
   167       show ?thesis
       
   168       proof (cases "es x")
       
   169         assume "es x = None"
       
   170         with asm env have False by simp
       
   171         thus ?thesis ..
       
   172       next
       
   173         fix e' assume es: "es x = Some e'"
       
   174         show ?thesis
       
   175         proof (cases "lookup e' xs")
       
   176           case None
       
   177           with asm env es have False by simp
       
   178           thus ?thesis ..
       
   179         next
       
   180           case Some
       
   181           with asm env es have "lookup e' xs = Some e"
       
   182             by simp
       
   183           hence "lookup e' (xs @ ys) = lookup e ys" by (rule hyp)
       
   184           with env es show ?thesis by simp
       
   185         qed
       
   186       qed
       
   187     qed
       
   188   }
       
   189 qed
       
   190 
       
   191 text {*
       
   192   \medskip Successful @{term lookup} deeper down an environment
       
   193   structure means we are able to peek further up as well.  Note that
       
   194   this is basically just the contrapositive statement of @{thm
       
   195   [source] lookup_append_none} above.
       
   196 *}
       
   197 
       
   198 theorem lookup_some_append:
       
   199   "lookup env (xs @ ys) = Some e ==> \<exists>e. lookup env xs = Some e"
       
   200 proof -
       
   201   assume "lookup env (xs @ ys) = Some e"
       
   202   hence "lookup env (xs @ ys) \<noteq> None" by simp
       
   203   hence "lookup env xs \<noteq> None"
       
   204     by (rule contrapos_nn) (simp only: lookup_append_none)
       
   205   thus ?thesis by simp
       
   206 qed
       
   207 
       
   208 text {*
       
   209   The subsequent statement describes in more detail how a successful
       
   210   @{term lookup} with a non-empty path results in a certain situation
       
   211   at any upper position.
       
   212 *}
       
   213 
       
   214 theorem lookup_some_upper: "!!env e.
       
   215   lookup env (xs @ y # ys) = Some e ==>
       
   216     \<exists>b' es' env'.
       
   217       lookup env xs = Some (Env b' es') \<and>
       
   218       es' y = Some env' \<and>
       
   219       lookup env' ys = Some e"
       
   220   (is "PROP ?P xs" is "!!env e. ?A env e xs ==> ?C env e xs")
       
   221 proof (induct ?P xs)
       
   222   fix env e
       
   223   let ?A = "?A env e" and ?C = "?C env e"
       
   224   {
       
   225     assume "?A []"
       
   226     hence "lookup env (y # ys) = Some e" by simp
       
   227     then obtain b' es' env' where
       
   228           env: "env = Env b' es'"
       
   229         and es': "es' y = Some env'"
       
   230         and look': "lookup env' ys = Some e"
       
   231       by (auto simp add: lookup_eq split: option.splits env.splits)
       
   232     from env have "lookup env [] = Some (Env b' es')" by simp
       
   233     with es' look' show "?C []" by blast
       
   234   next
       
   235     fix x xs
       
   236     assume hyp: "PROP ?P xs"
       
   237     assume "?A (x # xs)"
       
   238     then obtain b' es' env' where
       
   239           env: "env = Env b' es'"
       
   240         and es': "es' x = Some env'"
       
   241         and look': "lookup env' (xs @ y # ys) = Some e"
       
   242       by (auto simp add: lookup_eq split: option.splits env.splits)
       
   243     from hyp [OF look'] obtain b'' es'' env'' where
       
   244           upper': "lookup env' xs = Some (Env b'' es'')"
       
   245         and es'': "es'' y = Some env''"
       
   246         and look'': "lookup env'' ys = Some e"
       
   247       by blast
       
   248     from env es' upper' have "lookup env (x # xs) = Some (Env b'' es'')"
       
   249       by simp
       
   250     with es'' look'' show "?C (x # xs)" by blast
       
   251   }
       
   252 qed
       
   253 
       
   254 
       
   255 subsection {* The update operation *}
       
   256 
       
   257 text {*
       
   258   Update at a certain position in a nested environment may either
       
   259   delete an existing entry, or overwrite an existing one.  Note that
       
   260   update at undefined positions is simple absorbed, i.e.\ the
       
   261   environment is left unchanged.
       
   262 *}
       
   263 
       
   264 consts
       
   265   update :: "'c list => ('a, 'b, 'c) env option
       
   266     => ('a, 'b, 'c) env => ('a, 'b, 'c) env"
       
   267   update_option :: "'c list => ('a, 'b, 'c) env option
       
   268     => ('a, 'b, 'c) env option => ('a, 'b, 'c) env option"
       
   269 
       
   270 primrec (update)
       
   271   "update xs opt (Val a) =
       
   272     (if xs = [] then (case opt of None => Val a | Some e => e)
       
   273     else Val a)"
       
   274   "update xs opt (Env b es) =
       
   275     (case xs of
       
   276       [] => (case opt of None => Env b es | Some e => e)
       
   277     | y # ys => Env b (es (y := update_option ys opt (es y))))"
       
   278   "update_option xs opt None =
       
   279     (if xs = [] then opt else None)"
       
   280   "update_option xs opt (Some e) =
       
   281     (if xs = [] then opt else Some (update xs opt e))"
       
   282 
       
   283 hide const update_option
       
   284 
       
   285 text {*
       
   286   \medskip The characteristic cases of @{term update} are expressed by
       
   287   the following equalities.
       
   288 *}
       
   289 
       
   290 theorem update_nil_none: "update [] None env = env"
       
   291   by (cases env) simp_all
       
   292 
       
   293 theorem update_nil_some: "update [] (Some e) env = e"
       
   294   by (cases env) simp_all
       
   295 
       
   296 theorem update_cons_val: "update (x # xs) opt (Val a) = Val a"
       
   297   by simp
       
   298 
       
   299 theorem update_cons_nil_env:
       
   300     "update [x] opt (Env b es) = Env b (es (x := opt))"
       
   301   by (cases "es x") simp_all
       
   302 
       
   303 theorem update_cons_cons_env:
       
   304   "update (x # y # ys) opt (Env b es) =
       
   305     Env b (es (x :=
       
   306       (case es x of
       
   307         None => None
       
   308       | Some e => Some (update (y # ys) opt e))))"
       
   309   by (cases "es x") simp_all
       
   310 
       
   311 lemmas update.simps [simp del]
       
   312   and update_simps [simp] = update_nil_none update_nil_some
       
   313     update_cons_val update_cons_nil_env update_cons_cons_env
       
   314 
       
   315 lemma update_eq:
       
   316   "update xs opt env =
       
   317     (case xs of
       
   318       [] =>
       
   319         (case opt of
       
   320           None => env
       
   321         | Some e => e)
       
   322     | x # xs =>
       
   323         (case env of
       
   324           Val a => Val a
       
   325         | Env b es =>
       
   326             (case xs of
       
   327               [] => Env b (es (x := opt))
       
   328             | y # ys =>
       
   329                 Env b (es (x :=
       
   330                   (case es x of
       
   331                     None => None
       
   332                   | Some e => Some (update (y # ys) opt e)))))))"
       
   333   by (simp split: list.split env.split option.split)
       
   334 
       
   335 text {*
       
   336   \medskip The most basic correspondence of @{term lookup} and @{term
       
   337   update} states that after @{term update} at a defined position,
       
   338   subsequent @{term lookup} operations would yield the new value.
       
   339 *}
       
   340 
       
   341 theorem lookup_update_some:
       
   342   "!!env e. lookup env xs = Some e ==>
       
   343     lookup (update xs (Some env') env) xs = Some env'"
       
   344   (is "PROP ?P xs")
       
   345 proof (induct xs)
       
   346   fix env e :: "('a, 'b, 'c) env"
       
   347   {
       
   348     assume "lookup env [] = Some e"
       
   349     hence "env = e" by simp
       
   350     thus "lookup (update [] (Some env') env) [] = Some env'"
       
   351       by simp
       
   352   next
       
   353     fix x xs
       
   354     assume hyp: "PROP ?P xs"
       
   355     assume asm: "lookup env (x # xs) = Some e"
       
   356     show "lookup (update (x # xs) (Some env') env) (x # xs) = Some env'"
       
   357     proof (cases env)
       
   358       fix a assume "env = Val a"
       
   359       with asm have False by simp
       
   360       thus ?thesis ..
       
   361     next
       
   362       fix b es assume env: "env = Env b es"
       
   363       show ?thesis
       
   364       proof (cases "es x")
       
   365         assume "es x = None"
       
   366         with asm env have False by simp
       
   367         thus ?thesis ..
       
   368       next
       
   369         fix e' assume es: "es x = Some e'"
       
   370         show ?thesis
       
   371         proof (cases xs)
       
   372           assume "xs = []"
       
   373           with env show ?thesis by simp
       
   374         next
       
   375           fix x' xs' assume xs: "xs = x' # xs'"
       
   376           from asm env es have "lookup e' xs = Some e" by simp
       
   377           hence "lookup (update xs (Some env') e') xs = Some env'" by (rule hyp)
       
   378           with env es xs show ?thesis by simp
       
   379         qed
       
   380       qed
       
   381     qed
       
   382   }
       
   383 qed
       
   384 
       
   385 text {*
       
   386   \medskip The properties of displaced @{term update} operations are
       
   387   analogous to those of @{term lookup} above.  There are two cases:
       
   388   below an undefined position @{term update} is absorbed altogether,
       
   389   and below a defined positions @{term update} affects subsequent
       
   390   @{term lookup} operations in the obvious way.
       
   391 *}
       
   392 
       
   393 theorem update_append_none:
       
   394   "!!env. lookup env xs = None ==> update (xs @ y # ys) opt env = env"
       
   395   (is "PROP ?P xs")
       
   396 proof (induct xs)
       
   397   fix env :: "('a, 'b, 'c) env"
       
   398   {
       
   399     assume "lookup env [] = None"
       
   400     hence False by simp
       
   401     thus "update ([] @ y # ys) opt env = env" ..
       
   402   next
       
   403     fix x xs
       
   404     assume hyp: "PROP ?P xs"
       
   405     assume asm: "lookup env (x # xs) = None"
       
   406     show "update ((x # xs) @ y # ys) opt env = env"
       
   407     proof (cases env)
       
   408       fix a assume "env = Val a"
       
   409       thus ?thesis by simp
       
   410     next
       
   411       fix b es assume env: "env = Env b es"
       
   412       show ?thesis
       
   413       proof (cases "es x")
       
   414         assume es: "es x = None"
       
   415         show ?thesis
       
   416           by (cases xs) (simp_all add: es env fun_upd_idem_iff)
       
   417       next
       
   418         fix e assume es: "es x = Some e"
       
   419         show ?thesis
       
   420         proof (cases xs)
       
   421           assume "xs = []"
       
   422           with asm env es have False by simp
       
   423           thus ?thesis ..
       
   424         next
       
   425           fix x' xs' assume xs: "xs = x' # xs'"
       
   426           from asm env es have "lookup e xs = None" by simp
       
   427           hence "update (xs @ y # ys) opt e = e" by (rule hyp)
       
   428           with env es xs show "update ((x # xs) @ y # ys) opt env = env"
       
   429             by (simp add: fun_upd_idem_iff)
       
   430         qed
       
   431       qed
       
   432     qed
       
   433   }
       
   434 qed
       
   435 
       
   436 theorem update_append_some:
       
   437   "!!env e. lookup env xs = Some e ==>
       
   438     lookup (update (xs @ y # ys) opt env) xs = Some (update (y # ys) opt e)"
       
   439   (is "PROP ?P xs")
       
   440 proof (induct xs)
       
   441   fix env e :: "('a, 'b, 'c) env"
       
   442   {
       
   443     assume "lookup env [] = Some e"
       
   444     hence "env = e" by simp
       
   445     thus "lookup (update ([] @ y # ys) opt env) [] = Some (update (y # ys) opt e)"
       
   446       by simp
       
   447   next
       
   448     fix x xs
       
   449     assume hyp: "PROP ?P xs"
       
   450     assume asm: "lookup env (x # xs) = Some e"
       
   451     show "lookup (update ((x # xs) @ y # ys) opt env) (x # xs)
       
   452       = Some (update (y # ys) opt e)"
       
   453     proof (cases env)
       
   454       fix a assume "env = Val a"
       
   455       with asm have False by simp
       
   456       thus ?thesis ..
       
   457     next
       
   458       fix b es assume env: "env = Env b es"
       
   459       show ?thesis
       
   460       proof (cases "es x")
       
   461         assume "es x = None"
       
   462         with asm env have False by simp
       
   463         thus ?thesis ..
       
   464       next
       
   465         fix e' assume es: "es x = Some e'"
       
   466         show ?thesis
       
   467         proof (cases xs)
       
   468           assume xs: "xs = []"
       
   469           from asm env es xs have "e = e'" by simp
       
   470           with env es xs show ?thesis by simp
       
   471         next
       
   472           fix x' xs' assume xs: "xs = x' # xs'"
       
   473           from asm env es have "lookup e' xs = Some e" by simp
       
   474           hence "lookup (update (xs @ y # ys) opt e') xs =
       
   475             Some (update (y # ys) opt e)" by (rule hyp)
       
   476           with env es xs show ?thesis by simp
       
   477         qed
       
   478       qed
       
   479     qed
       
   480   }
       
   481 qed
       
   482 
       
   483 text {*
       
   484   \medskip Apparently, @{term update} does not affect the result of
       
   485   subsequent @{term lookup} operations at independent positions, i.e.\
       
   486   in case that the paths for @{term update} and @{term lookup} fork at
       
   487   a certain point.
       
   488 *}
       
   489 
       
   490 theorem lookup_update_other:
       
   491   "!!env. y \<noteq> (z::'c) ==> lookup (update (xs @ z # zs) opt env) (xs @ y # ys) =
       
   492     lookup env (xs @ y # ys)"
       
   493   (is "PROP ?P xs")
       
   494 proof (induct xs)
       
   495   fix env :: "('a, 'b, 'c) env"
       
   496   assume neq: "y \<noteq> z"
       
   497   {
       
   498     show "lookup (update ([] @ z # zs) opt env) ([] @ y # ys) =
       
   499       lookup env ([] @ y # ys)"
       
   500     proof (cases env)
       
   501       case Val
       
   502       thus ?thesis by simp
       
   503     next
       
   504       case Env
       
   505       show ?thesis
       
   506       proof (cases zs)
       
   507         case Nil
       
   508         with neq Env show ?thesis by simp
       
   509       next
       
   510         case Cons
       
   511         with neq Env show ?thesis by simp
       
   512       qed
       
   513     qed
       
   514   next
       
   515     fix x xs
       
   516     assume hyp: "PROP ?P xs"
       
   517     show "lookup (update ((x # xs) @ z # zs) opt env) ((x # xs) @ y # ys) =
       
   518       lookup env ((x # xs) @ y # ys)"
       
   519     proof (cases env)
       
   520       case Val
       
   521       thus ?thesis by simp
       
   522     next
       
   523       fix y es assume env: "env = Env y es"
       
   524       show ?thesis
       
   525       proof (cases xs)
       
   526         assume xs: "xs = []"
       
   527         show ?thesis
       
   528         proof (cases "es x")
       
   529           case None
       
   530           with env xs show ?thesis by simp
       
   531         next
       
   532           case Some
       
   533           with hyp env xs and neq show ?thesis by simp
       
   534         qed
       
   535       next
       
   536         fix x' xs' assume xs: "xs = x' # xs'"
       
   537         show ?thesis
       
   538         proof (cases "es x")
       
   539           case None
       
   540           with env xs show ?thesis by simp
       
   541         next
       
   542           case Some
       
   543           with hyp env xs neq show ?thesis by simp
       
   544         qed
       
   545       qed
       
   546     qed
       
   547   }
       
   548 qed
       
   549 
       
   550 end