【发布时间】:2020-09-24 10:38:38
【问题描述】:
Haskell base documentation 表示“A Word 是无符号整数类型,大小与 Int 相同。”
如何获取Int 并将其位表示转换为Word,所以我得到一个Word 值,其位表示与原始Int 相同(即使它们表示的数值将不同)?
我不能使用fromIntegral,因为那会改变位表示。
我可以使用the Bits class 循环遍历这些位,但我怀疑这会很慢 - 而且我不需要进行任何类型的位操作。我想要某种可以编译为无操作(或接近它)的函数,因为没有进行任何转换。
动机
我想使用IntSet 作为一个快速整数集实现——然而,我真正想在其中存储的是Words。我觉得我可以通过在它们之间快速转换来创建一个由IntSet 支持的WordSet。问题是,我不想按值转换,因为我不想截断Word 值的上半部分:我只想保持位表示相同。
【问题讨论】:
-
unsafeCoerce似乎确实可以解决问题,但我不确定它是否值得信任。 -
unsafeCoerce#的文档表明它可以(因为支持在相同大小的未装箱类型之间进行转换)。不过,我确实更喜欢int2Word#和word2Int#,因为它们更明确 - 最好有编译器的声音支持。 -
您确定
fromIntegral更改了位表示吗?比如我用ghci运行fromIntegral (2147483648 :: Word32) :: Int32,它返回-2147483648,这是正确的等价位表示。 -
这是一个strange implementation,它确实进行了位转换——我承认没有尝试过,因为这种行为完全令人惊讶,完全不是我对
fromIntegral的期望。 -
@IsaacvanBakel 事实上,
fromIntegral :: Int -> Word确实 保留位模式,fromIntegral :: Word -> Int也是如此。由于fromIntegral = fromInteger . toInteger和Integer对2^(WORD_SIZE_IN_BITS-1)< x < 2^WORD_SIZE_IN_BITS - 1之间的整数表示错误,这看起来像是一个值转换,但这是值中的位模式保留。为了获得更好的性能,该实现有一个 GHC 重写规则,将fromInteger替换为int2Word#和word2Int#。