Dav*_*ani 5 haskell coercion ghc
我是用实验unsafeCoerce用Int8和Word8,我发现了一些奇怪的行为(我反正).
Word8是一个8位无符号数,范围为0-255.Int8是一个带符号的8位数字,范围从-128..127.
因为它们都是8位数,所以我认为相互强制转换是安全的,只需返回8位值,就好像它是有符号/无符号的一样.
例如,unsafeCoerce (-1 :: Int8) :: Word8我希望得到一个Word8255 的值(因为有符号int中的位表示-1与unsigned int中的255相同).
但是,当我执行强制执行时,Word8行为很奇怪:
> GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
> import Data.Int
> import Data.Word
> import Unsafe.Coerce
> class ShowType a where typeName :: a -> String
> instance ShowType Int8 where typeName _ = "Int8"
> instance ShowType Word8 where typeName _ = "Word8"
> let x = unsafeCoerce (-1 :: Int8) :: Word8
> show x
"-1"
> typeName x
"Word8"
> show (x + 0)
"255"
> :t x
x :: Word8
> :t (x + 0)
(x + 0) :: Word8
Run Code Online (Sandbox Code Playgroud)
我不明白这里show x是怎么回事的"-1".如果你看一下map show [minBound..maxBound :: Word8],Word8结果没有可能的价值"-1".此外,即使类型未更改,如何向数字添加0也会更改行为?奇怪的是,它似乎只是Show受影响的类 - 我的ShowType类返回正确的值.
最后,代码fromIntegral (-1 :: Int8) :: Word8按预期工作,并返回255,并正常工作show.编译器是否可以将此代码简化为无操作?
请注意,这个问题仅仅是出于对ghc在低级别中如何表示类型的好奇心.我实际上并没在我的代码中使用unsafeCoerce.
Mik*_*kov 10
像@kosmikus说,既Int8和Int16使用的是实施Int#,这是32比特宽的上32位架构(和Word8和Word16是Word#引擎盖下).GHC.Prim中的这篇评论更详细地解释了这一点.
因此,让我们找出为什么这个实现选择会导致您看到的行为:
> let x = unsafeCoerce (-1 :: Int8) :: Word8
> show x
"-1"
Run Code Online (Sandbox Code Playgroud)
在Show例如Word8 被定义为
instance Show Word8 where
showsPrec p x = showsPrec p (fromIntegral x :: Int)
Run Code Online (Sandbox Code Playgroud)
而且fromIntegral只是fromInteger . toInteger.toIntegerfor 的定义Word8是
toInteger (W8# x#) = smallInteger (word2Int# x#)
Run Code Online (Sandbox Code Playgroud)
where smallInteger(在integer-gmp中定义)是
smallInteger :: Int# -> Integer
smallInteger i = S# i
Run Code Online (Sandbox Code Playgroud)
并且word2Int#是一个类型的primopWord# -> Int# - reinterpret_cast<int>在C++中的类比.这就解释了为什么你-1在第一个例子中看到:该值只是重新解释为有符号整数并打印出来.
现在,为什么会加入0到x给你255?看一下我们看到的Num实例Word8:
(W8# x#) + (W8# y#) = W8# (narrow8Word# (x# `plusWord#` y#))
Run Code Online (Sandbox Code Playgroud)
因此,看起来这narrow8Word#是一个罪魁祸首.让我们检查:
> import GHC.Word
> import GHC.Prim
> case x of (W8# w) -> (W8# (narrow8Word# w))
255
Run Code Online (Sandbox Code Playgroud)
的确是.这就解释了为什么添加0不是无操作 - Word8添加实际上会将值限制在预期范围内.
| 归档时间: |
|
| 查看次数: |
167 次 |
| 最近记录: |