<div><br><div class="gmail_quote"><div dir="auto">On Tue, 8 May 2018 at 2:00 PM, Clinton Mead <<a href="mailto:redirect@vodafone.co.nz">redirect@vodafone.co.nz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra"><div class="gmail_quote">On Tue, May 8, 2018 at 11:17 AM, Anthony Clayden <span><<a href="mailto:anthony_clayden@clear.net.nz" target="_blank">anthony_clayden@clear.net.nz</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br><div class="gmail_quote"><span><div dir="auto">On Tue, 8 May 2018 at 12:20 AM, Clinton Mead <<a href="mailto:redirect@vodafone.co.nz" target="_blank">redirect@vodafone.co.nz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><br></div><div>Firstly, you refer to <a href="https://wiki.haskell.org/GHC/AdvancedOverlap" target="_blank">https://wiki.haskell.org/GHC/AdvancedOverlap</a>. Unfortunately (unless I've missed something) these involve listing all the instances of parent classes. I'm trying to avoid that. Indeed if I have to explicitly list all the instances I might as well write them the normal way so I'm not sure what the point of any trickery is.</div><div></div></div></blockquote><div dir="auto"><br></div></span><div dir="auto">Yes that approach does need declaring instances of `ShowPred` (or in general `XXXPred`), which doubles-up the instances for `Show` (or `XXX`). That approach is making a closed world: for every type `t`, return either `True` or `False` that it has an instance for `Show`.</div><div dir="auto"><br></div><div dir="auto">I'm not sure what you mean by "write them the normal way"? Just declaring `t` an instance of `Show` doesn't expose that in any way you can run type-level functions over it.</div></div></div></blockquote><div><br></div></div></div></div><div><div class="gmail_extra"><div class="gmail_quote"><div>By normal way as in if I need to list every instance as "ShowPred", I might as well just scrap "ShowPred" and just write them directly as instances of "Print". i.e.</div><div></div></div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">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:</div><div dir="auto"><br></div><div dir="auto">type instance ShowPred [a] = ShowPred a                                              -- implication</div><div dir="auto">type instance ShowPred (a, b) = And (ShowPred a) (ShowPred b)       -- conjunction</div><div dir="auto"><br></div><div dir="auto">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 ...</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_quote"><span><div dir="auto"><br></div></span><div dir="auto">I'm puzzled what it is you're trying to do. <br></div></div></div>
</blockquote></div></div></div><div><div class="gmail_extra"><div class="gmail_quote"></div><br></div><div class="gmail_extra">I'm trying to select instances based on whether constraints are fulfilled. </div><div class="gmail_extra"><br></div><div class="gmail_extra">... consider:<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">

<div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">class Join' m (IsSatisfied m) (IsSatisfied m) => Join m where</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">  join :: m (m a) -> m a</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"><br></font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">instance 

<span style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Join' m (IsSatisfied m) (IsSatisfied m) => Join m where</span>

</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><span style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><font face="monospace, monospace">  join = join'</font></span></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"></font></div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">?? I think that context needs something like</div><div dir="auto"><br></div><div dir="auto">instance Join' m (IsMonad m) (IsComonad m) => Join m where ...</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra"><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"><br></font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">instance Monad m => Join' m Satisfied t2 where</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">  join' x = x >>= id</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"><br></font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">instance Comonad m => Join' m t1 Satisfied where</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">  join' = extract</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"><br></font></div>

<div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">instance Comonad m => Join' m Satisfied Satisfied where</font></div><div class="gmail_extra" style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">  join' = extract</font></div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto">You've just invoked a closed world: you're relying on the compiler determining some `m0` is _not_ a `Comonad`.</div><div dir="auto"><br></div><div dir="auto">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`. </div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra">...</div></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra"><div class="gmail_extra" dir="auto"><br>"IsSatisfied" only needs to assert when the constraint is satisfied, it doesn't need to assert when it isn't, ...</div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">Yes it does for what you're asking to do.</div><div dir="auto"><br></div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="gmail_extra"><div class="gmail_extra" dir="auto"> so I don't think it violates the open world assumption. Also GHC has this information to give an answer to IsSatisfied, it simply has to try to solve the constraint and if it succeeds reduce it to Satisfied, and if it doesn't it just does nothing.</div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">To the contrary: what you want it to do is select a different instance.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">AntC</div></div></div>