doc-src/TutorialI/Advanced/Partial.thy
changeset 11196 bb4ede27fcb7
parent 11158 5652018b809a
child 11256 49afcce3bada
equal deleted inserted replaced
11195:65ede8dfe304 11196:bb4ede27fcb7
     4 Throughout the tutorial we have emphasized the fact that all functions
     4 Throughout the tutorial we have emphasized the fact that all functions
     5 in HOL are total. Hence we cannot hope to define truly partial
     5 in HOL are total. Hence we cannot hope to define truly partial
     6 functions. The best we can do are functions that are
     6 functions. The best we can do are functions that are
     7 \emph{underdefined}\index{underdefined function}:
     7 \emph{underdefined}\index{underdefined function}:
     8 for certain arguments we only know that a result
     8 for certain arguments we only know that a result
     9 exists, but we don't know what it is. When defining functions that are
     9 exists, but we do not know what it is. When defining functions that are
    10 normally considered partial, underdefinedness turns out to be a very
    10 normally considered partial, underdefinedness turns out to be a very
    11 reasonable alternative.
    11 reasonable alternative.
    12 
    12 
    13 We have already seen an instance of underdefinedness by means of
    13 We have already seen an instance of underdefinedness by means of
    14 non-exhaustive pattern matching: the definition of @{term last} in
    14 non-exhaustive pattern matching: the definition of @{term last} in
    18 consts hd :: "'a list \<Rightarrow> 'a"
    18 consts hd :: "'a list \<Rightarrow> 'a"
    19 primrec "hd (x#xs) = x"
    19 primrec "hd (x#xs) = x"
    20 
    20 
    21 text{*\noindent
    21 text{*\noindent
    22 although it generates a warning.
    22 although it generates a warning.
    23 
       
    24 Even ordinary definitions allow underdefinedness, this time by means of
    23 Even ordinary definitions allow underdefinedness, this time by means of
    25 preconditions:
    24 preconditions:
    26 *}
    25 *}
    27 
    26 
    28 constdefs minus :: "nat \<Rightarrow> nat \<Rightarrow> nat"
    27 constdefs minus :: "nat \<Rightarrow> nat \<Rightarrow> nat"
    62 standard mathematical division function.
    61 standard mathematical division function.
    63 
    62 
    64 As a more substantial example we consider the problem of searching a graph.
    63 As a more substantial example we consider the problem of searching a graph.
    65 For simplicity our graph is given by a function (@{term f}) of
    64 For simplicity our graph is given by a function (@{term f}) of
    66 type @{typ"'a \<Rightarrow> 'a"} which
    65 type @{typ"'a \<Rightarrow> 'a"} which
    67 maps each node to its successor, and the task is to find the end of a chain,
    66 maps each node to its successor, i.e.\ the graph is really a tree.
    68 i.e.\ a node pointing to itself. Here is a first attempt:
    67 The task is to find the end of a chain, modelled by a node pointing to
       
    68 itself. Here is a first attempt:
    69 @{prop[display]"find(f,x) = (if f x = x then x else find(f, f x))"}
    69 @{prop[display]"find(f,x) = (if f x = x then x else find(f, f x))"}
    70 This may be viewed as a fixed point finder or as one half of the well known
    70 This may be viewed as a fixed point finder or as one half of the well known
    71 \emph{Union-Find} algorithm.
    71 \emph{Union-Find} algorithm.
    72 The snag is that it may not terminate if @{term f} has non-trivial cycles.
    72 The snag is that it may not terminate if @{term f} has non-trivial cycles.
    73 Phrased differently, the relation
    73 Phrased differently, the relation
    89 
    89 
    90 text{*\noindent
    90 text{*\noindent
    91 The recursion equation itself should be clear enough: it is our aborted
    91 The recursion equation itself should be clear enough: it is our aborted
    92 first attempt augmented with a check that there are no non-trivial loops.
    92 first attempt augmented with a check that there are no non-trivial loops.
    93 
    93 
    94 What complicates the termination proof is that the argument of
    94 What complicates the termination proof is that the argument of @{term find}
    95 @{term find} is a pair. To express the required well-founded relation
    95 is a pair. To express the required well-founded relation we employ the
    96 we employ the predefined combinator @{term same_fst} of type
    96 predefined combinator @{term same_fst} of type
    97 @{text[display]"('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> ('b\<times>'b)set) \<Rightarrow> (('a\<times>'b) \<times> ('a\<times>'b))set"}
    97 @{text[display]"('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> ('b\<times>'b)set) \<Rightarrow> (('a\<times>'b) \<times> ('a\<times>'b))set"}
    98 defined as
    98 defined as
    99 @{thm[display]same_fst_def[no_vars]}
    99 @{thm[display]same_fst_def[no_vars]}
   100 This combinator is designed for recursive functions on pairs where the first
   100 This combinator is designed for
   101 component of the argument is passed unchanged to all recursive
   101 recursive functions on pairs where the first component of the argument is
   102 calls. Given a constraint on the first component and a relation on the second
   102 passed unchanged to all recursive calls. Given a constraint on the first
   103 component, @{term same_fst} builds the required relation on pairs.
   103 component and a relation on the second component, @{term same_fst} builds the
   104 The theorem @{thm[display]wf_same_fst[no_vars]}
   104 required relation on pairs.  The theorem
   105 is known to the well-foundedness prover of \isacommand{recdef}.
   105 @{thm[display]wf_same_fst[no_vars]}
   106 Thus well-foundedness of the given relation is immediate.
   106 is known to the well-foundedness prover of \isacommand{recdef}.  Thus
   107 Furthermore, each recursive call descends along the given relation:
   107 well-foundedness of the relation given to \isacommand{recdef} is immediate.
   108 the first argument stays unchanged and the second one descends along
   108 Furthermore, each recursive call descends along that relation: the first
   109 @{term"step1 f"}. The proof merely requires unfolding of some definitions.
   109 argument stays unchanged and the second one descends along @{term"step1
       
   110 f"}. The proof merely requires unfolding of some definitions, as specified in
       
   111 the \isacommand{hints} above.
   110 
   112 
   111 Normally you will then derive the following conditional variant of and from
   113 Normally you will then derive the following conditional variant of and from
   112 the recursion equation
   114 the recursion equation
   113 *}
   115 *}
   114 
   116 
   202 @{term while} at all? The only reason is executability: the recursion
   204 @{term while} at all? The only reason is executability: the recursion
   203 equation for @{term while} is a directly executable functional
   205 equation for @{term while} is a directly executable functional
   204 program. This is in stark contrast to guarded recursion as introduced
   206 program. This is in stark contrast to guarded recursion as introduced
   205 above which requires an explicit test @{prop"x \<in> dom f"} in the
   207 above which requires an explicit test @{prop"x \<in> dom f"} in the
   206 function body.  Unless @{term dom} is trivial, this leads to a
   208 function body.  Unless @{term dom} is trivial, this leads to a
   207 definition that is impossible to execute (or prohibitively slow).
   209 definition that is impossible to execute or prohibitively slow.
   208 Thus, if you are aiming for an efficiently executable definition
   210 Thus, if you are aiming for an efficiently executable definition
   209 of a partial function, you are likely to need @{term while}.
   211 of a partial function, you are likely to need @{term while}.
   210 *}
   212 *}
   211 
   213 
   212 (*<*)end(*>*)
   214 (*<*)end(*>*)