简体   繁体   中英

Is there any way to tell 64-bit GHC to treat Int as Int32?

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?

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 eg GHC does to support Int64 on 32 bit machines.

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).

Javascript数字表示为双精度数,因此请使用Double

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM