Generic logic

This is perhaps not optimally polished, but I'm putting it out here for feedback.  The idea is that a "logic" is essentially a modality, and we can define all the logical operations relative to "a logic", with PAT-logic and (-1)-logic as important special cases.  More description can be found in the comments.  I included LEM as an example of how to use this kind of generic logic; next up would be AC, which is potentially parametrized by 2 or 3 different modalities/logics.

I had to make a bunch of choices about how to implement it, and my only indication that they're the right ones is that nothing else I tried worked as well.  So I'm very open to suggestions, up to and including "this is a terrible idea".

One particular infelicity is that this change slows down the compilation of `V.v` by almost a factor of 3.  I don't have any idea why that might be, but if it's going to consistently do that whenever we make heavy use of `hexists` (which `V.v` is currently the only theory that does), then one might argue that this is not worth it.
Good point.  No, I don't.  So I guess I think that there are some hypotheses where the names don't carry any more information than the type.  These get named with single letters, or with a letter followed by a number.  (I'm a bit unhappy with `fs : Funext`, but not too unhappy, because we never use it by name.)  If you're going to give the name of `A -> B -> Empty` any information at all, beyond picking a class of single letters based on the type, I'd say give it easily comprehensible information.