<div dir="auto">Ah, I think I see what you mean. One option:<div dir="auto"><br></div><div dir="auto">class EqFoo1 f where</div><div dir="auto">  liftEqSame :: (a -> a -> Bool)</div><div dir="auto">    -> f a -> f a -> Bool</div><div dir="auto">  -- and/or the more principled</div><div dir="auto">  liftEqOnSame ::</div><div dir="auto">    Eq b => (a -> b) -> f a -> f a -> Bool</div><div dir="auto">class (Functor f, EqFoo1) => EqBar1 where</div><div dir="auto">  liftEqDifferent :: (a -> b -> Bool)</div><div dir="auto">    -> f a -> f b -> Bool</div><div dir="auto">  -- and/or the more principled</div><div dir="auto">  liftEqOnDifferent :: Eq c</div><div dir="auto">    => (a -> c) -> (b -> c) -> f a -> f b -> Bool</div><div dir="auto"><br></div><div dir="auto">This wouldn't be the best for my hypothetical Arr type, but I don't know that it's an important enough case to worry about.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mar 15, 2018 11:55 PM, "Gershom B" <<a href="mailto:gershomb@gmail.com">gershomb@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div id="m_9219007330690673646bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">On March 15, 2018 at 11:50:45 PM, David Feuer (<a href="mailto:david.feuer@gmail.com" target="_blank">david.feuer@gmail.com</a>) wrote:</div> <div><blockquote type="cite" class="m_9219007330690673646clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span><div><div></div><div><div dir="auto"><div>For Map and HashMap, yes, Eq2 and Ord2 are the problem. For Set and HashSet, Eq1 and Ord1 are trouble.</div><div dir="auto"><br></div><div dir="auto">The advantage of the flexibility is that for a Functor or Bifunctor you get an optimization: instead of mapping a function or two over each container to give them the same type and then comparing the results, you can fuse it all into one operation. Of course, the same thing could also be done for each type using rewrite rules, but that's kind of gross.</div></div></div></div></span></blockquote></div><p>Right. But it is the possibility of this optimization that breaks things. In particular, `Set` is not a functor (and does not permit mapping over it), but it _should_ be able to be an instance of Eq1. </p><p>-g</p><div><blockquote type="cite" class="m_9219007330690673646clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span><div><div><div dir="auto"><div dir="auto"></div></div></div></div></span></blockquote></div></div>
</blockquote></div></div>