GHC: Ticket #5419: integer-gmp no longer exports S# and J#
http://ghc.haskell.org/trac/ghc/ticket/5419
<p>
Commit <a class="missing changeset" rel="nofollow" title="No changeset d8f636ec19a21cc4c22a8d1b45217436838aeebb in the repository">d8f636ec19a21cc4c22a8d1b45217436838aeebb</a> effectively removed the constructors from the package export list and libraries that depend on them (text and HsOpenSSL here) are now broken.
</p>
en-usGHChttp://ghc.haskell.org/trac/ghc/chrome/site/ghc_logo.png
http://ghc.haskell.org/trac/ghc/ticket/5419
Trac 1.0.7tibbeThu, 18 Aug 2011 09:27:52 GMTcc set
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:1
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:1
<ul>
<li><strong>cc</strong>
<em>johan.tibell@…</em> added
</li>
</ul>
TickettibbeThu, 18 Aug 2011 09:49:28 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:2
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:2
<p>
I don't quite understand the motivation for this change:
</p>
<pre class="wiki">No need to export Integer from GHC.Integer.GMP.Internals
This caused an odd dependency in the module hierarchy.
</pre><p>
Could someone please elaborate on what this odd dependency is?
</p>
<p>
We do need to export the constructors somewhere as some algorithms can only be implemented efficiently in terms of them (e.g. hexadecimal encoding of <tt>Integer</tt>s).
</p>
TickettibbeThu, 18 Aug 2011 11:10:19 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:3
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:3
<p>
The dependency chain used to be: <tt>GHC.Integer</tt> -> <tt>GHC.Integer.GMP.Internals</tt> -> <tt>GHC.Integer.Type</tt>.
</p>
<p>
The dependency chain is now: <tt>GHC.Integer</tt> -> <tt>GHC.Integer.Type</tt> -> <tt>GHC.Integer.GMP.Internals</tt>.
</p>
<p>
If I understand Ian's intentions right he thinks it's odd for a module in the <tt>GHC.Integer.GMP</tt> namespace to appear between two modules from the <tt>GHC.Integer</tt> namespace. Fair enough. Then I suggest we add <tt>GHC.Integer.Internals</tt> that exports the <tt>Integer</tt> constructors.
</p>
TickettibbeThu, 18 Aug 2011 12:34:16 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:4
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:4
<p>
Here's a list of packages that are currently broken:
</p>
<ul><li>blaze-textual-0.2.0.4
</li><li>fixed-precision-0.4.0
</li><li>bytestring-show-0.3.5
</li><li>text-0.11.1.5
</li><li>text-format-0.3.0.5
</li></ul><p>
I don't quite understand the namespace design of integer-gmp: The whole package is for GMP like things (which we derive from the package name) but only parts of the module hierarchy mention GMP. This makes me a bit confused as to where the <tt>Integer</tt> constructors should be exported from.
</p>
TickettibbeThu, 18 Aug 2011 12:49:48 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:5
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:5
<p>
After thinking about this for a while I've convinced myself that we want to export the constructors from <tt>GHC.Integer.GMP.Internals</tt>. <tt>GHC.Integer</tt> and its submodules (except <tt>GMP</tt> in the case of integer-gmp and <tt>Simple</tt> in the case of integer-simple) represent the API shared between the two packages. If you want to import something that's specific to one package then you should mention <tt>GMP</tt> or <tt>Simple</tt> explicitly. With this reasoning the <tt>GHC.Integer.Type</tt> module in each package should be moved into the implementation specific namespace (<tt>GMP</tt> or <tt>Simple</tt>) and be exported (in part) through <tt>GMP.Internals</tt> or <tt>Simple.Internals</tt>.
</p>
TicketsimonpjThu, 18 Aug 2011 16:37:01 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:6
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:6
<p>
Ian is away, until the middle of nex week. You refactoring makes sense to me.
</p>
<p>
It's tricky trying to simultaneously support
</p>
<ul><li>Two different implementations of <tt>Integer</tt>. That suggests that the representation of <tt>Integer</tt> should be opaque.
</li><li>Optimisations for small integers, which needs to see the representation.
</li></ul><p>
The two goals are in tension. I believe the uses of <tt>S#</tt> in client packages are there to optimise the small-integer case (can anyone confirm?).
</p>
<p>
I wonder whether a way to square this circle would be to have an abstract pseudo-constructor function whose type is that of <tt>S#</tt>:
</p>
<pre class="wiki"> smallInteger :: Int# -> Integer
</pre><p>
The idea is:
</p>
<ul><li>The compiler desugars small <tt>Integer</tt> constants into uses of <tt>smallInteger</tt>.
</li><li>Rewrite rules can match on <tt>(smallInteger x)</tt>.
</li><li><tt>smallInteger</tt> is inlined late.
</li><li>Two different implementations of the <tt>Integer</tt> API could implement <tt>smallInteger</tt> quite differently.
</li></ul><p>
As I understan Johan's proposed change, client packages that mentioned <tt>S#</tt> would not build against a different <tt>Integer</tt> implementation. With the above idea, they would.
</p>
<p>
But I've learned that it's easy to miss something in this territory.
</p>
<p>
Simon Ian and I were already discussing something like
</p>
<pre class="wiki"> bigInteger :: ByteString -> Integer
</pre><p>
for big integer constants, to avoid the absurd stuff in <a class="closed ticket" href="http://ghc.haskell.org/trac/ghc/ticket/5284" title="bug: Simplifier performance regression (or infinite loop) (closed: fixed)">#5284</a>. The <tt>ByteString</tt> (or <tt>MachAddr</tt> or something, I forget what) is supposed to be the bit representation of the <tt>Integer</tt>. Different implementations of <tt>Integer</tt> would mangle it in different ways to build their respective internal representations.
Simon
</p>
TickettibbeThu, 18 Aug 2011 17:09:01 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:7
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:7
<p>
Here's and example use of the internals:
</p>
<p>
<a class="ext-link" href="https://github.com/bos/text/blob/master/Data/Text/Lazy/Builder/Int.hs#L95"><span class="icon"></span>https://github.com/bos/text/blob/master/Data/Text/Lazy/Builder/Int.hs#L95</a>
</p>
<p>
Note that the <tt>Integer</tt> value being pretty-printed here typically won't be known statically, so optimizing constants won't help here.
</p>
<p>
Hashing <tt>Integer</tt>s is another important case. We can hash an <tt>Integer</tt> much faster if we can first hash the <tt>Int#</tt> component and then zip over the <tt>ByteArray#</tt>.
</p>
<p>
We could create a projection function of type <tt>Integer -> (Int#, ByteArray#)</tt> which would be a simple constructor unwrapping in integer-gmp and some kind of conversion in integer-simple.
</p>
<p>
Note that packages can access <tt>S#</tt> directly but still be portable to other integer implementation by using CPP.
</p>
TicketsimonpjThu, 18 Aug 2011 22:43:30 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:8
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:8
<p>
Well, maybe hashing and printing should be part of the common API, supported by all implementations of <tt>Integer</tt>.
</p>
<p>
Or, if you want something super-optimised, a library author might want to depend on a <em>particular</em> implementation of the <tt>Integer</tt> API, in which case s/he is free to do so.
</p>
<p>
But you probably don't want to do so <em>accidentally</em>.
</p>
TickettibbeFri, 19 Aug 2011 08:58:49 GMT
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:9
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:9
<p>
I actually think the way it used to work was OK. If you wanted to depend on a particular implementation you could import e.g. <tt>GHC.Integer.GMP.Internals</tt>. I agree in principle that the (internal) module dependencies were a bit wacky, but it seems hard to avoid them given the requirements of <tt>PrelNames</tt> to name a module exported by all integer-* packages and require that this module must define the data type in question, instead of just re-export it.
</p>
TicketiglooWed, 24 Aug 2011 17:41:13 GMTpriority changed; owner, milestone set
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:10
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:10
<ul>
<li><strong>priority</strong>
changed from <em>normal</em> to <em>highest</em>
</li>
<li><strong>owner</strong>
set to <em>igloo</em>
</li>
<li><strong>milestone</strong>
set to <em>7.4.1</em>
</li>
</ul>
TicketpumpkinThu, 25 Aug 2011 02:17:49 GMTcc changed
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:11
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:11
<ul>
<li><strong>cc</strong>
<em>pumpkingod@…</em> added
</li>
</ul>
<p>
This would also make the mpfr bindings Ed Kmett and I are working on nicer, as mpfr has dedicated functions for interoperating with gmp integers (it's built on top of gmp).
</p>
TicketiglooThu, 25 Aug 2011 11:05:15 GMTstatus changed; resolution set
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:12
http://ghc.haskell.org/trac/ghc/ticket/5419#comment:12
<ul>
<li><strong>status</strong>
changed from <em>new</em> to <em>closed</em>
</li>
<li><strong>resolution</strong>
set to <em>fixed</em>
</li>
</ul>
<p>
Fixed by:
</p>
<pre class="wiki">commit 65c73842bca2f075b65f418a5ff34753b185e0d7
Author: Ian Lynagh <igloo@earth.li>
Date: Thu Aug 25 11:18:07 2011 +0100
Export Integer(..) from GHC.Integer.GMP.Internals again; fixes #5419
The GMP primitives are now in GHC.Integer.GMP.Prim instead.
</pre>
Ticket