<div dir="ltr"><div>I like the idea of marking partial functions with HasCallStack.<br></div><div>But I'd like to point out that we also have class methods where some but not all implementations are partial, such as foldr1 in Foldable.</div><div><br></div><div>Should methods like these also get a HasCallStack constraint?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am So., 16. Juni 2019 um 14:30 Uhr schrieb LuoChen <<a href="mailto:luochen1990@gmail.com">luochen1990@gmail.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail-m_-2161109858183269905markdown-here-wrapper"><h2 id="gmail-m_-2161109858183269905motivation" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.4em;border-bottom:1px solid rgb(238,238,238)">Motivation</h2>
<p style="margin:0px 0px 1.2em">Partial functions in base (especially Prelude) often cause runtime errors and is hard to locate.</p>
<p style="margin:0px 0px 1.2em">(<a href="https://gist.github.com/luochen1990/6fcbb0fa4c0c7caa1b242188eb586d1f" target="_blank">here</a> is a document about the concept of totality and partial function, ignore this if you are familiar with them)</p>
<p style="margin:0px 0px 1.2em">For example, consider the following piece of code:</p>
<pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">import GHC.Stack

foo :: HasCallStack => [Int] -> Int
foo xs = last xs + 1

xs :: [Int]
xs = []

main :: IO ()
main = do
    print $ foo xs
</code></pre><p style="margin:0px 0px 1.2em">In this case, the error message will tell nothing about <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">foo</code>, and the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint is totally helpless, because the call stack is cut off by the call to <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">last</code> which without <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint.</p>
<p style="margin:0px 0px 1.2em">My current workaround is define my own wrapper functions with <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint for some mostly used partial functions to make them traceable, and use the wrapper (the traceable version) whenever I need them.</p>
<p style="margin:0px 0px 1.2em">e.g.</p>
<pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">last' :: HasCallStack => [a] -> a
last' xs = case xs of [] -> error "abuse last"; _ -> last xs</code></pre><p style="margin:0px 0px 1.2em">So, IMHO, if our goal is to make errors in haskell traceable, then <strong>only providing <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> mechanism is not enough, we have to provide traceable base package and prelude at the same time</strong>.</p>
<p style="margin:0px 0px 1.2em">Further more, all untraceable partial functions are considered to be harmful, and should not be exported by any package. Because an improper call to an untraceable partial function will cut off the call stack, and <a href="https://gist.github.com/luochen1990/94179a2492ff7d1ca45153645f1bb449" target="_blank">here is a demonstration about that</a>.</p>
<p style="margin:0px 0px 1.2em">On the other hand, is it ever necessary for us to add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> for a total function? Or we can ask, is it possible that a call to a total function cause runtime error?  Maybe it’s a NO, since a total function will also crash when the machine is Out Of Memory, but that is also the only situation I can find out. So I suggest that we add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint only for partial functions, and IMHO this could be a good balance for better debugging experience and less runtime overhead.</p>
<h2 id="gmail-m_-2161109858183269905proposal" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.4em;border-bottom:1px solid rgb(238,238,238)">Proposal</h2>
<ol style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint for all partial functions in base package</li>
<li style="margin:0.5em 0px">suggest all programmers to add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint for their exported partial functions when they release a package</li>
<li style="margin:0.5em 0px">provide a compiler option <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">-fignore-hascallstack</code> to toggle off the effect of <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint in case somebody need best performance</li>
</ol>
<h2 id="gmail-m_-2161109858183269905other-considerations" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.4em;border-bottom:1px solid rgb(238,238,238)">Other Considerations</h2>
<h3 id="gmail-m_-2161109858183269905how-to-get-a-full-list-of-partial-functions-provided-by-the-base-package-" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.3em">How to get a full list of partial functions provided by the base package?</h3>
<p style="margin:0px 0px 1.2em">I wanted to provide a full list of partial functions exported by the base package in this post, but I find it is hard, since Haskell have no totality checking mechanism like Idris have, and there are no consistent keyword like “total” or “partial” in document, so it takes a lot of work to list all the partial functions of a package by check every item manually. Maybe we can work on this list later — when it’s turned out to be worth after some discussion.</p>
<p style="margin:0px 0px 1.2em"><a href="https://gist.github.com/luochen1990/5b7a0844701413486da595b9b997f3c2" target="_blank">Here</a> is part of the list that I have tidied for several modules of the base package.</p>
<h3 id="gmail-m_-2161109858183269905how-to-encourage-all-package-contributors-to-obey-the-rule-see-proposal-2-" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.3em">How to encourage all package contributors to obey the rule (see proposal #2)?</h3>
<p style="margin:0px 0px 1.2em">I don’t know, but I think there may be some other rules to obey when contributing packages. Maybe we can just add this into the list.</p>
<p style="margin:0px 0px 1.2em">Obviously, the final perfect solution should be let the compiler to check the totality of functions, and automatically add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> for the ones which the compiler cannot confirm it’s totality. But this seems too far away from us, since we still doesn’t have dependent type haskell yet.</p>
<h3 id="gmail-m_-2161109858183269905how-to-deal-with-recursive-partial-functions-" style="margin:1.3em 0px 1em;padding:0px;font-weight:bold;font-size:1.3em">How to deal with recursive partial functions?</h3>
<p style="margin:0px 0px 1.2em">Since the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> constraint affects the performance (not only because of the runtime overhead, but also it’s influence on optimization strategy), It is best not to add <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">HasCallStack</code> on recursive functions.</p>
<p style="margin:0px 0px 1.2em">In most of the cases, we can just check the input shallowly before everything start, just like how we deal with the non-recursive ones.</p>
<p style="margin:0px 0px 1.2em">But in some other cases, we need to go deep to recognize the invalidity of the input. A trivial solution is just perform a deep check before everything start, but the checking phase seems expensive.</p>
<p style="margin:0px 0px 1.2em">The best solution, IMHO, is to make the recursive part a total function, wrap the return value into <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">Maybe</code> or some similar things, and the partial version is just the total version combined <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">fromJust</code>. In this way, we avoid the single input checking phase and left the error awareing logic where it was before this translation.</p>
<div title="MDH:TW90aXZhdGlvbjxicj4tLS0tLS0tLS0tPGJyPjxicj5QYXJ0aWFsIGZ1bmN0aW9ucyBpbiBiYXNl
IChlc3BlY2lhbGx5IFByZWx1ZGUpIG9mdGVuIGNhdXNlIHJ1bnRpbWUgZXJyb3JzIGFuZCBpcyBo
YXJkIHRvIGxvY2F0ZS48YnI+PGJyPihbaGVyZV0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vbHVv
Y2hlbjE5OTAvNmZjYmIwZmE0YzBjN2NhYTFiMjQyMTg4ZWI1ODZkMWYpIGlzIGEgZG9jdW1lbnQg
YWJvdXQgdGhlIGNvbmNlcHQgb2YgdG90YWxpdHkgYW5kIHBhcnRpYWwgZnVuY3Rpb24sIGlnbm9y
ZSB0aGlzIGlmIHlvdSBhcmUgZmFtaWxpYXIgd2l0aCB0aGVtKTxicj48YnI+Rm9yIGV4YW1wbGUs
IGNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgcGllY2Ugb2YgY29kZTo8YnI+PGJyPmBgYDxicj5pbXBv
cnQgR0hDLlN0YWNrPGJyPjxicj5mb28gOjogSGFzQ2FsbFN0YWNrID0mZ3Q7IFtJbnRdIC0mZ3Q7
IEludDxicj5mb28geHMgPSBsYXN0IHhzICsgMTxicj48YnI+eHMgOjogW0ludF08YnI+eHMgPSBb
XTxicj48YnI+bWFpbiA6OiBJTyAoKTxicj5tYWluID0gZG88YnI+wqAgwqAgcHJpbnQgJCBmb28g
eHM8YnI+YGBgPGJyPjxicj5JbiB0aGlzIGNhc2UsIHRoZSBlcnJvciBtZXNzYWdlIHdpbGwgdGVs
bCBub3RoaW5nIGFib3V0IGBmb29gLCBhbmQgdGhlIGBIYXNDYWxsU3RhY2tgIGNvbnN0cmFpbnQg
aXMgdG90YWxseSBoZWxwbGVzcywgYmVjYXVzZSB0aGUgY2FsbCBzdGFjayBpcyBjdXQgb2ZmIGJ5
IHRoZSBjYWxsIHRvIGBsYXN0YCB3aGljaCB3aXRob3V0IGBIYXNDYWxsU3RhY2tgIGNvbnN0cmFp
bnQuPGJyPjxicj5NeSBjdXJyZW50IHdvcmthcm91bmQgaXMgZGVmaW5lIG15IG93biB3cmFwcGVy
IGZ1bmN0aW9ucyB3aXRoIGBIYXNDYWxsU3RhY2tgIGNvbnN0cmFpbnQgZm9yIHNvbWUgbW9zdGx5
IHVzZWQgcGFydGlhbCBmdW5jdGlvbnMgdG8gbWFrZSB0aGVtIHRyYWNlYWJsZSwgYW5kIHVzZSB0
aGUgd3JhcHBlciAodGhlIHRyYWNlYWJsZSB2ZXJzaW9uKSB3aGVuZXZlciBJIG5lZWQgdGhlbS48
YnI+PGJyPmUuZy48YnI+PGJyPmBgYDxicj5sYXN0JyA6OiBIYXNDYWxsU3RhY2sgPSZndDsgW2Fd
IC0mZ3Q7IGE8YnI+bGFzdCcgeHMgPSBjYXNlIHhzIG9mIFtdIC0mZ3Q7IGVycm9yICJhYnVzZSBs
YXN0IjsgXyAtJmd0OyBsYXN0IHhzPGJyPmBgYDxicj48YnI+U28sIElNSE8sIGlmIG91ciBnb2Fs
IGlzIHRvIG1ha2UgZXJyb3JzIGluIGhhc2tlbGwgdHJhY2VhYmxlLCB0aGVuICoqb25seSBwcm92
aWRpbmcgYEhhc0NhbGxTdGFja2AgbWVjaGFuaXNtIGlzIG5vdCBlbm91Z2h0LCB3ZSBoYXZlIHRv
IHByb3ZpZGUgdHJhY2VhYmxlIGJhc2UgcGFja2FnZSBhbmQgcHJlbHVkZSBhdCB0aGUgc2FtZSB0
aW1lKiouPGJyPjxicj5GdXJ0aGVyIG1vcmUsIGFsbCB1bnRyYWNlYWJsZSBwYXJ0aWFsIGZ1bmN0
aW9ucyBhcmUgY29uc2lkZXJlZCB0byBiZSBoYXJtZnVsLCBhbmQgc2hvdWxkIG5vdCBiZSBleHBv
cnRlZCBieSBhbnkgcGFja2FnZS4gQmVjYXVzZSBhbiBpbXByb3BlciBjYWxsIHRvIGFuIHVudHJh
Y2VhYmxlIHBhcnRpYWwgZnVuY3Rpb24gd2lsbCBjdXQgb2ZmIHRoZSBjYWxsIHN0YWNrLCBhbmQg
W2hlcmUgaXMgYSBkZW1vbnN0cmF0aW9uIGFib3V0IHRoYXRdKGh0dHBzOi8vZ2lzdC5naXRodWIu
Y29tL2x1b2NoZW4xOTkwLzk0MTc5YTI0OTJmZjdkMWNhNDUxNTM2NDVmMWJiNDQ5KS48YnI+PGJy
Pk9uIHRoZSBvdGhlciBoYW5kLCBpcyBpdCBldmVyIG5lY2Vzc2FyeSBmb3IgdXMgdG8gYWRkIGBI
YXNDYWxsU3RhY2tgIGZvciBhIHRvdGFsIGZ1bmN0aW9uPyBPciB3ZSBjYW4gYXNrLCBpcyBpdCBw
b3NzaWJsZSB0aGF0IGEgY2FsbCB0byBhIHRvdGFsIGZ1bmN0aW9uIGNhdXNlIHJ1bnRpbWUgZXJy
b3I/IMKgTWF5YmUgaXQncyBhIE5PLCBzaW5jZSBhIHRvdGFsIGZ1bmN0aW9uIHdpbGwgYWxzbyBj
cmFzaCB3aGVuIHRoZSBtYWNoaW5lIGlzIE91dCBPZiBNZW1vcnksIGJ1dCB0aGF0IGlzIGFsc28g
dGhlIG9ubHkgc2l0dWF0aW9uIEkgY2FuIGZpbmQgb3V0LiBTbyBJIHN1Z2dlc3QgdGhhdCB3ZSBh
ZGQgYEhhc0NhbGxTdGFja2AgY29uc3RyYWludCBvbmx5IGZvciBwYXJ0aWFsIGZ1bmN0aW9ucywg
YW5kIElNSE8gdGhpcyBjb3VsZCBiZSBhIGdvb2QgYmFsYW5jZSBmb3IgYmV0dGVyIGRlYnVnZ2lu
ZyBleHBlcmllbmNlIGFuZCBsZXNzIHJ1bnRpbWUgb3ZlcmhlYWQuPGJyPjxicj5Qcm9wb3NhbDxi
cj4tLS0tLS0tLTxicj48YnI+MS4gYWRkIGBIYXNDYWxsU3RhY2tgIGNvbnN0cmFpbnQgZm9yIGFs
bCBwYXJ0aWFsIGZ1bmN0aW9ucyBpbiBiYXNlIHBhY2thZ2U8YnI+Mi4gc3VnZ2VzdCBhbGwgcHJv
Z3JhbW1lcnMgdG8gYWRkIGBIYXNDYWxsU3RhY2tgIGNvbnN0cmFpbnQgZm9yIHRoZWlyIGV4cG9y
dGVkIHBhcnRpYWwgZnVuY3Rpb25zIHdoZW4gdGhleSByZWxlYXNlIGEgcGFja2FnZTxicj4zLiBw
cm92aWRlIGEgY29tcGlsZXIgb3B0aW9uIGAtZmlnbm9yZS1oYXNjYWxsc3RhY2tgIHRvIHRvZ2ds
ZSBvZmYgdGhlIGVmZmVjdCBvZiBgSGFzQ2FsbFN0YWNrYCBjb25zdHJhaW50IGluIGNhc2Ugc29t
ZWJvZHkgbmVlZCBiZXN0IHBlcmZvcm1hbmNlPGJyPjxicj5PdGhlciBDb25zaWRlcmF0aW9uczxi
cj4tLS0tLS0tLS0tLS0tLS0tLS0tLTxicj48YnI+IyMjIEhvdyB0byBnZXQgYSBmdWxsIGxpc3Qg
b2YgcGFydGlhbCBmdW5jdGlvbnMgcHJvdmlkZWQgYnkgdGhlIGJhc2UgcGFja2FnZT88YnI+PGJy
Pkkgd2FudGVkIHRvIHByb3ZpZGUgYSBmdWxsIGxpc3Qgb2YgcGFydGlhbCBmdW5jdGlvbnMgZXhw
b3J0ZWQgYnkgdGhlIGJhc2UgcGFja2FnZSBpbiB0aGlzIHBvc3QsIGJ1dCBJIGZpbmQgaXQgaXMg
aGFyZCwgc2luY2UgSGFza2VsbCBoYXZlIG5vIHRvdGFsaXR5IGNoZWNraW5nIG1lY2hhbmlzbSBs
aWtlIElkcmlzIGhhdmUsIGFuZCB0aGVyZSBhcmUgbm8gY29uc2lzdGVudCBrZXl3b3JkIGxpa2Ug
4oCcdG90YWzigJ0gb3Ig4oCccGFydGlhbOKAnSBpbiBkb2N1bWVudCwgc28gaXQgdGFrZXMgYSBs
b3Qgb2Ygd29yayB0byBsaXN0IGFsbCB0aGUgcGFydGlhbCBmdW5jdGlvbnMgb2YgYSBwYWNrYWdl
IGJ5IGNoZWNrIGV2ZXJ5IGl0ZW0gbWFudWFsbHkuIE1heWJlIHdlIGNhbiB3b3JrIG9uIHRoaXMg
bGlzdCBsYXRlciAtLSB3aGVuIGl0J3MgdHVybmVkIG91dCB0byBiZSB3b3J0aCBhZnRlciBzb21l
IGRpc2N1c3Npb24uPGJyPjxicj5bSGVyZV0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vbHVvY2hl
bjE5OTAvNWI3YTA4NDQ3MDE0MTM0ODZkYTU5NWI5Yjk5N2YzYzIpIGlzIHBhcnQgb2YgdGhlIGxp
c3QgdGhhdCBJIGhhdmUgdGlkaWVkIGZvciBzZXZlcmFsIG1vZHVsZXMgb2YgdGhlIGJhc2UgcGFj
a2FnZS48YnI+PGJyPiMjIyBIb3cgdG8gZW5jb3VyYWdlIGFsbCBwYWNrYWdlIGNvbnRyaWJ1dG9y
cyB0byBvYmV5IHRoZSBydWxlIChzZWUgcHJvcG9zYWwgIzIpPzxicj48YnI+SSBkb24ndCBrbm93
LCBidXQgSSB0aGluayB0aGVyZSBtYXkgYmUgc29tZSBvdGhlciBydWxlcyB0byBvYmV5IHdoZW4g
Y29udHJpYnV0aW5nIHBhY2thZ2VzLiBNYXliZSB3ZSBjYW4ganVzdCBhZGQgdGhpcyBpbnRvIHRo
ZSBsaXN0Ljxicj48YnI+T2J2aW91c2x5LCB0aGUgZmluYWwgcGVyZmVjdCBzb2x1dGlvbiBzaG91
bGQgYmUgbGV0IHRoZSBjb21waWxlciB0byBjaGVjayB0aGUgdG90YWxpdHkgb2YgZnVuY3Rpb25z
LCBhbmQgYXV0b21hdGljYWxseSBhZGQgYEhhc0NhbGxTdGFja2AgZm9yIHRoZSBvbmVzIHdoaWNo
IHRoZSBjb21waWxlciBjYW5ub3QgY29uZmlybSBpdCdzIHRvdGFsaXR5LiBCdXQgdGhpcyBzZWVt
cyB0b28gZmFyIGF3YXkgZnJvbSB1cywgc2luY2Ugd2Ugc3RpbGwgZG9lc24ndCBoYXZlIGRlcGVu
ZGVudCB0eXBlIGhhc2tlbGwgeWV0Ljxicj48YnI+IyMjIEhvdyB0byBkZWFsIHdpdGggcmVjdXJz
aXZlIHBhcnRpYWwgZnVuY3Rpb25zPzxicj48YnI+U2luY2UgdGhlIGBIYXNDYWxsU3RhY2tgIGNv
bnN0cmFpbnQgYWZmZWN0cyB0aGUgcGVyZm9ybWFuY2UgKG5vdCBvbmx5IGJlY2F1c2Ugb2YgdGhl
IHJ1bnRpbWUgb3ZlcmhlYWQsIGJ1dCBhbHNvIGl0J3MgaW5mbHVlbmNlIG9uIG9wdGltaXphdGlv
biBzdHJhdGVneSksIEl0IGlzIGJlc3Qgbm90IHRvIGFkZCBgSGFzQ2FsbFN0YWNrYCBvbiByZWN1
cnNpdmUgZnVuY3Rpb25zLjxicj48YnI+SW4gbW9zdCBvZiB0aGUgY2FzZXMsIHdlIGNhbiBqdXN0
IGNoZWNrIHRoZSBpbnB1dCBzaGFsbG93bHkgYmVmb3JlIGV2ZXJ5dGhpbmcgc3RhcnQsIGp1c3Qg
bGlrZSBob3cgd2UgZGVhbCB3aXRoIHRoZSBub24tcmVjdXJzaXZlIG9uZXMuPGJyPjxicj5CdXQg
aW4gc29tZSBvdGhlciBjYXNlcywgd2UgbmVlZCB0byBnbyBkZWVwIHRvIHJlY29nbml6ZSB0aGUg
aW52YWxpZGl0eSBvZiB0aGUgaW5wdXQuIEEgdHJpdmlhbCBzb2x1dGlvbiBpcyBqdXN0IHBlcmZv
cm0gYSBkZWVwIGNoZWNrIGJlZm9yZSBldmVyeXRoaW5nIHN0YXJ0LCBidXQgdGhlIGNoZWNraW5n
IHBoYXNlIHNlZW1zIGV4cGVuc2l2ZS48YnI+PGJyPlRoZSBiZXN0IHNvbHV0aW9uLCBJTUhPLCBp
cyB0byBtYWtlIHRoZSByZWN1cnNpdmUgcGFydCBhIHRvdGFsIGZ1bmN0aW9uLCB3cmFwIHRoZSBy
ZXR1cm4gdmFsdWUgaW50byBgTWF5YmVgIG9yIHNvbWUgc2ltaWxhciB0aGluZ3MsIGFuZCB0aGUg
cGFydGlhbCB2ZXJzaW9uIGlzIGp1c3QgdGhlIHRvdGFsIHZlcnNpb24gY29tYmluZWQgYGZyb21K
dXN0YC4gSW4gdGhpcyB3YXksIHdlIGF2b2lkIHRoZSBzaW5nbGUgaW5wdXQgY2hlY2tpbmcgcGhh
c2UgYW5kIGxlZnQgdGhlIGVycm9yIGF3YXJlaW5nIGxvZ2ljIHdoZXJlIGl0IHdhcyBiZWZvcmUg
dGhpcyB0cmFuc2xhdGlvbi48YnI+" style="height:0px;width:0px;max-height:0px;max-width:0px;overflow:hidden;font-size:0em;padding:0px;margin:0px"></div></div><br></div>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>