declare_monad :
  string * { bind : term, unit : term, ignorebind : term option,
             choice : term option, fail : term option, guard : term option }
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.
HOL  Kananaskis-14