4
votes

I'm writing a Haskell to Javascript code generator, using GHC as a library. Since Javascript doesn't have an integer type and its Number type can only represent integers up to 2⁵³ properly, I'm representing integers as Numbers, explicitly performing all arithmetic modulo 2³². This works very well with a 32 bit GHC, but rather worse with the 64 bit version.

GHC will happily coerce Int64 values to Ints and interpret Int constants as 64 bit values (0xffffffff turns into 4294967295 rather than -1, for example) and that's causing all sorts of annoying problems.

The compiler works very well for "normal" web stuff even on a 64 bit system, provided that the standard libraries are built on a 32 bit machine, but "please don't use large-ish numbers, OK?" isn't something you want to see in your compiler's manual. Some of the problems (but not all) can be alleviated by compiling with -O0, but that (unsurprisingly) produces code that's not only slow, but also way too big.

So, I need to stop GHC from assuming that Int and Int64 are equivalent. Is this even possible?

3
If you want 32-bit integers, why not use GHC.Int.Int32?n. 1.8e9-where's-my-share m.
That is indeed possible, but "you have to use Int32 rather than Int because Int is broken" isn't something you want to see in your compiler's manual either.valderman
What promise made about Int is broken?n. 1.8e9-where's-my-share m.
No need to even import GHC-specific modules. Data.Int contains Int32 (it's re-exported from GHC.Int in GHC but that shouldn't matter)copumpkin

3 Answers

7
votes

That is not possible, without using a 32 bit GHC.

The Haskell Language standard says that the only thing you know about the Int type is that it has

at least the range [-2^29 .. 2^29-1

So you can happily truncate Int values larger than this, and still be a fully compliant Haskell 2010 implementation!

However, you should probably not do this, and instead look for a 64 bit integer type for JavaScript. The same trick as e.g. GHC does to support Int64 on 32 bit machines.

3
votes

As a rule "Int" should only be used for things where 2^29 is big enough, and apart from that it doesn't matter. Anywhere else use either Integer or one of the Data.Word or Data.Int (Int8, Int16 etc) types. Good examples include most sizes and counts (but not file sizes, which can easily exceed 2^32 these days)

Classic bad example: Control.Concurrent.threadDelay :: Int -> IO (). The argument is the pause time in uSec. 2^29 uSec = 8.94784853 minutes (according to Google Calculator). The argument should have been Integer, or at least Word64 (584 554.531 years).

1
votes

Javascript numbers are represented as doubles, so use Double.