<div dir="ltr"><div><div><br></div>Assuming the Generic instance is a stable interface, I would create a traversal of that, feeding directly into a Blake2b-implementation (a fast SHA3 finalist, tweaked).<br><br><br></div><div>This gives you a cryptographically strong fingerprint, space usage is flexible (extract as many bytes as you want), is fast (~1GB/s), and with low complexity/external dependencies.<br><br></div><div><br>Alexander<br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 7, 2014 at 10:30 PM, Ozgun Ataman <span dir="ltr"><<a href="mailto:ozataman@gmail.com" target="_blank">ozataman@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">Hello everybody,<div><br></div><div>I have a little question I wanted to run by the folks here. I've run into it several times over the past few years and would love to lock down a good answer.</div><div><br></div><div>What's the best way to "fingerprint" a Haskell object into, say, ByteString, so that this fingerprint can be used as the "lookup key" in a database (for example) and be trusted that it will remain constant over time even as the underlying libraries evolve?</div><div><br></div><div>Here's a simple example:</div><div><ul><li>Say I'm building a manual index on top of a key-value store (redis, dynamodb, etc.)<br><br></li><li>I want my keys to be arbitrary tuples (or similar records) that may contain various fields in them<br><br></li><li>I would like to avoid ad-hoc, hand-written MyTuple -> ByteString and ByteString -> MyTuple conversions. However, Generic derivations, template-haskell, etc. are acceptable<br><br></li><li>Notice how your fingerprint, which is used as a lookup key in the database, has to remain stationary. If it changes even by a single bit over time for the same MyTuple, the key-value store will NOT be able to find the index associated with MyTuple at this later time</li></ul><div><br></div></div><div>Here are some ideas (and related concepts) I've considered and used over the years:</div><div><ul><li>Hand-write a "Prism' MyTuple ByteString". This works, but is tedious and error-prone.<br><br></li><li>Use Serialize/Binary and trust that the encode/decode pair will produce results consistently in 5 years (dangerous territory!)<br><br></li><li>Use SafeCopy, which is great for ensuring timeless decoding of the *value* in the index, but can we be sure that fingerprint (MyTuple -> ByteString) conversion is persistent? What if SafeCopy authors one day decide to encode tuples differently? They would write the migrations to transparently handle legacy code for *values*, but not for *keys*. Also notice here how migrations help with the ByteString -> MyTuple leg, but do not ensure MyTuple -> ByteString produces the same ByteString over time.<br><br></li><li>Hashable would've been nice, but there is NO guarantee of persistent results, even across multiple runs of the same code</li></ul><div>What would be your preferred solution?</div></div><div><br></div><div>Thank you,</div><div>Oz</div><div><br></div><div><br></div><div><br><div><br></div><div><br></div></div></div>
<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br></div>