Reputation: 139058
Suppose I've got a lot of values of type Word8
, Word16
, and Word32
lying around. I want to widen them, interpreting some as signed and some as unsigned, so that I can store them all in an [Int64]
. I know I can write something like the following function, where the first argument specifies whether we want to interpret the Word8
as signed or not:
convert8 :: Bool -> Word8 -> Int64
convert8 False i = fromIntegral i
convert8 True i = fromIntegral (fromIntegral i :: Int8)
This gives me the result I want:
*Main> convert8 False 128
128
*Main> convert8 True 128
-128
The double fromIntegral
feels inelegant to me, though. Is there some nicer way to say "interpret this Word
as a signed integer and stick it in a bigger Int
"?
Upvotes: 4
Views: 824
Reputation: 62848
From what I recall, GHC stores all integers as one machine word. (In other words, a 32-bit GHC stores integers as 32 bits. A 64-bit GHC stores them as 64 bits.) So if you request an 8-bit integer, it stores it as 32 bits anyway, but only uses the first 8 bits.
Because of this, I'm fairly sure that widening or narrowing using fromIntegral
is actually no-op at run-time; all it does is change the type signature, with no run-time cost. (Converting from unsigned to signed might be doing sign extension, however. I'm not completely sure how that part works. It's probably still one machine instruction though.)
In short, I think the double fromIntegral
is probably about the best way to do this. You could manually implement sign extension yourself, but the built-in machine instruction for doing this is likely to be faster.
Upvotes: 4