declare_monadmonadsyntax.declare_monad :
string * { bind : term, unit : term, ignorebind : term option,
choice : term option, fail : term option, guard : term option }
->
unit
Declares a monad type for which the do/od syntax can be used.
A call to declare_monad(mname, minfo) alters the
internal “monad database” so that a subsequent call to
enable_monad mname will cause do/od syntax to try to use
the terms in minfo as interpretations of that syntax. The
only compulsory values are the unit and bind
values, which should have types conforming to the pattern
:α M and :α -> β M respectively. For
example, the list monad would have M instantiated by the
pattern :_ list, while the reader monad would have
M instantiated by the pattern
:'env -> _.
The ignorebind field allows the user to provide a
specific constant to interpret a bind where the second
argument ignores the value. If this is not provided, then syntax such as
do M1; M2; od will be interpreted as
bind M1 (K M2), where K is the constant
combinator.
The remaining fields are used when the monad has a notion of failure.
For example, the option monad uses NONE as the appropriate
value for fail. The choice term should be of
type :α M -> α M -> α M, and should return the first
value if it is not a failure, or otherwise use the second argument. The
supported syntax for choice is ++.
Finally, the guard field should be a term of type
:bool -> unit M. It is rendered as assert b
with b a boolean value. If b is true, the
monad “returns” the unit value; if b is false the monad
fails.
The information declared with a call to declare_monad is
exported with the current theory and is thus available to descendent
theories.
Never fails. However, the terms present in the monad-information record must have appropriate types if strange type-checking errors on subsequent uses of the do/od syntax are to be avoided.
A set monad could be declared:
> declare_monad("set", {
unit = “λa. {a}”, bind = “λs f. BIGUNION (IMAGE f s)”,
ignorebind = NONE,
fail = SOME “{}”, guard = SOME “λb. if b then {()} else {}”,
choice = SOME “$UNION”
});
This function does not even care if the constants have the right respective types; it certainly doesn’t care if the constants satisfy the monadic axioms.