问题
Here is a sample function:
fun divide :: "enat option ⇒ enat option ⇒ real option" where
"divide (Some ∞) _ = None"
| "divide _ (Some ∞) = None"
| "divide _ (Some 0) = None"
| "divide (Some a) (Some b) = Some (a / b)"
| "divide _ _ = None"
Isabelle HOL shows me the following error:
Malformed definition:
Non-constructor pattern not allowed in sequential mode.
⋀uw_. divide uw_ (Some 0) = None
Why pattern-matching works fine for Some ∞
and doesn't work for Some 0
? ∞
is a constant for class infinity
and 0
is a constant for class zero
. What is the difference between these constants?
回答1:
Pattern matching with fun
only works for constructors, which are typically generated using datatype
and codatatype
commands. (In fact, it suffices if they are registered as free constructors using free_constructors
.) The extended naturals enat
as defined in ~~/src/HOL/Library/Extended_Nat
have two such constructors registered: ∞
and enat :: nat ⇒ enat
. So 0
is not a constructor of enat
, but of the ordinary naturals nat
. So if you write
| "divide _ (Some (enat 0)) = None"
instead, it will work because there are only registered constructors in the patterns.
Conversely, if your theory imports Coinductive_Nat
from the APF entry Coinductive
, then enat
is registered to have the constructors 0
and eSuc
, i.e., as if it were a codatatype. Then you can pattern-match on 0
, but you can no longer pattern match on ∞
.
来源:https://stackoverflow.com/questions/45932256/how-to-use-complex-patterns-in-functions