No you haven't got it: there's a default/fallback instance for `Print` that applies if `ShowPred` comes out `False`. Also if you have `True/False` you can do Boolean logic over the result:
type instance ShowPred [a] = ShowPred a -- implication
type instance ShowPred (a, b) = And (ShowPred a) (ShowPred b) -- conjunction
including either/or logic, which is where your O.P. started. (Although we seem to have come a long way from that.) So turning to your latest example ...
?? I think that context needs something like
instance Join' m (IsMonad m) (IsComonad m) => Join m where ...
So if some `m0` is both a `Comonad` and a `Monad`, you want to prefer the `Comonad` method. If `m0` is a `Monad` but not a `Comonad`, use the `Monad` method.
You've just invoked a closed world: you're relying on the compiler determining some `m0` is _not_ a `Comonad`.
Technically: your instances for `Join'` overlap. So the compiler's inference selection must determine which is the more specific, given some particular `m0` with its `t1, t2` result from `IsSatisfied`. It can select head `Join' m Satisfied t2` only if it can prove `t2` is apart from `Satisfied`.
Yes it does for what you're asking to do.
To the contrary: what you want it to do is select a different instance.
AntC