<div dir="auto">> <span style="white-space:pre-wrap;background-color:rgb(255,255,255)">It's occurred to me that one could write a class C t which is satisfied</span></div><pre style="white-space:pre-wrap;background-color:rgb(255,255,255)"><div dir="auto">> whenever (A t) or (B t) is satisfied like so:</div><div dir="auto"><br></div><div dir="auto">Hi Clinton, this sounds like you might want "Choosing a type-class instance based on the context" <div><a href="https://wiki.haskell.org/GHC/AdvancedOverlap">https://wiki.haskell.org/GHC/AdvancedOverlap</a></div></div><div dir="auto"><br></div><div dir="auto">
> ---
>
> data Satisfied
>
> type family IsSatisfiable :: Constraint -> Type</div><div dir="auto"><br></div><div dir="auto">That type family is doing the same job as auxiliary class `ShowPred` on that wiki page.</div><div dir="auto"><br></div><div dir="auto">Rather than all the machinery you give for the disjunction, you could use another type family:</div><div dir="auto"><br></div><div dir="auto">type family EitherSatisfied :: Type -> Type -> Type</div><div dir="auto">instance EitherSatisfied Satisfied tb = Satisfied</div><div dir="auto">instance EitherSatisfied ta Satisfied = Satisfied</div><div dir="auto"><br></div><div dir="auto">Those two instances do overlap (as you expected); and they exhibit confluence, aka coincident overlap (they produce the same result); so that's fine.</div><div dir="auto"><br></div><div dir="auto">But you haven't given any instances for `IsSatisfiable`. How do you expect to get from the Constraint to the `Satisfied` type?</div><div dir="auto"><br></div><div dir="auto">You say</div><div dir="auto"><br></div><div dir="auto">> <span style="font-family:-apple-system,HelveticaNeue">IsSatisfiable c = Satisfied -- (if c is satisfiable)</span><br><br></div><div dir="auto">What are you going to put for `c`? If you follow that wiki page, you'll need to in effect repeat every instance decl for classes `A, B`:</div><div dir="auto"><br></div><div dir="auto">instance A Int where ...</div><div dir="auto"><br></div><div dir="auto">type instance IsSatisfiable (A Int) = Satisfied</div><div dir="auto"><br></div><div dir="auto">(The wiki page was written before there were type families, so type class `ShowPred` has a Functional Dependency giving a type-level Boolean result.)</div><div dir="auto">
</div><div dir="auto">Your `C t` class becomes</div><div dir="auto">
class EitherSatisfied ( IsSatisfiable (A t)) ( IsSatisfiable (B t)) ~ Satisfied => C t where ...</div><div dir="auto"><br></div><div dir="auto">----</div><div dir="auto"><br></div><div dir="auto">Nowadays there's a better way: make Associated Types for the two classes, give them a default instance:</div><div dir="auto"><br></div><div dir="auto">class A t where</div><div dir="auto"> type APred t</div><div dir="auto"> type instance APred t = Satisfied</div><div dir="auto"> ...</div><div dir="auto"><br></div><div dir="auto">class B t where</div><div dir="auto"> type BPred t</div><pre style="white-space:pre-wrap"><div dir="auto"> type instance BPred t = Satisfied</div><div dir="auto"> ...</div></pre><div dir="auto"><br></div><div dir="auto">Now every instance defined for `A, B` in effect automatically gives you `APred, BPred` instances. <span style="font-family:-apple-system,HelveticaNeue">Then</span></div><div dir="auto"><br></div><div dir="auto">class EitherSatisifed (APred t) (BPred t) ~ Satisfied => C t where ...</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">AntC</div><div dir="auto"><br></div></pre>