<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Aug 20, 2014 at 11:28 AM, Johan Tibell <span dir="ltr"><<a href="mailto:johan.tibell@gmail.com" target="_blank">johan.tibell@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="">On Wed, Aug 20, 2014 at 10:23 AM, Erik Hesselink <span dir="ltr"><<a href="mailto:hesselink@gmail.com" target="_blank">hesselink@gmail.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">As I understood, the question was if GHC would first compare pointers,<br>
and only call the Eq instance if the pointers are not equal. I guess<br>
this would be safe, but I don't think GHC does such a thing.</blockquote><div><br></div></div><div>I think the reason it isn't done is that it's not always an optimization. We do it manually in e.g. bytestring.</div>



<div> </div></div></div></div>
<br></blockquote></div><br></div><div class="gmail_extra">There are two cases I can think of where it would also change the semantics of the code:<br><br></div><div class="gmail_extra">1. An Eq instance that doesn't obey the reflective property (not recommended):<br>

<br></div><div class="gmail_extra">data BadEq = BadEq<br></div><div class="gmail_extra">instance Eq BadEq where<br></div><div class="gmail_extra">    BadEq == BadEq = False<br><br></div><div class="gmail_extra">2. Eq instances intended to avoid timing attacks, by always comparing the entire data structure.<br>

<br></div><div class="gmail_extra">newtype SlowEq a = SlowEq [a]<br></div><div class="gmail_extra">instance Eq a => Eq (SlowEq a) where<br></div><div class="gmail_extra">    SlowEq x == SlowEq y = slowAnd $ length x == length y : zipWith (==) x y<br>

<br></div><div class="gmail_extra">slowAnd =<br></div><div class="gmail_extra">    loop True<br></div><div class="gmail_extra">  where<br></div><div class="gmail_extra">    loop !x [] = x<br></div><div class="gmail_extra">

    loop !x (!y:ys) = loop (x && y) ys<br><br></div><div class="gmail_extra">(Note: not actually tested.) It's difficult for me to imagine a case though where a timing attack could result on two data structures sharing the same pointer; usually we'd be talking about comparing two ByteStrings or Texts that come from very different sources.<br>

<br></div><div class="gmail_extra">Michael<br></div></div>