2013-04-05 88 views
3

假设我有很多值得关注的类型为Word8,Word16Word32。我想扩大它们,将一些解释为已签名,一些解码为未签名,以便我可以将它们全部存储在[Int64]中。我知道我可以写类似下面的函数,其中第一个参数指定我们是否要解释Word8作为签署与否:将无符号整数解释为在扩展时签名

convert8 :: Bool -> Word8 -> Int64 
convert8 False i = fromIntegral i 
convert8 True i = fromIntegral (fromIntegral i :: Int8) 

这给了我我想要的结果:

*Main> convert8 False 128 
128 
*Main> convert8 True 128 
-128 

尽管如此,双fromIntegral对我来说感觉不雅。有没有更好的方法来说:“将Word解释为一个有符号的整数并且将它放在更大的Int”?

+0

是否存在'convert8 True = negate的问题。 fromIntegral'? – 2013-04-05 03:14:50

+0

嗯,是的,因为我不想否定 - 我想将无符号整数解释为signed,这意味着例如'convert8 True 1 == 1'。 – 2013-04-05 03:43:21

+0

但我认为'convert True'意味着你想要一个负值...这样一个令人困惑的设计!如果布尔值为“真”,且所需值为负值,那么当使用带符号的类型(即带符号类型的正值超出范围)时,该字为负值? – 2013-04-05 04:02:27

回答

3

从我记得,GHC将所有整数存储为一个机器字。 (换句话说,一个32位的GHC将整数存储为32位,一个64位的GHC将它们存储为64位)。因此,如果你请求一个8位整数,它将它存储为32位,但只有使用前8位是。因此,我相当确定使用fromIntegral的扩展或缩小在运行时实际上是不可用的;它所做的只是更改类型签名,而没有运行时成本。 (从无符号转换为有符号可能会做符号扩展,但是我不完全确定那个部分是如何工作的,但它可能仍然是一个机器指令)。最好的方法来做到这一点。您可以自己手动实施符号扩展,但执行此操作的内置机器指令可能会更快。