Eksperymentowałem z unsafeCoerce
z Int8
i Word8
i znalazłem zaskakujące zachowanie (dla mnie w każdym razie).wyświetla powracającą niewłaściwą wartość, gdy jest używana z niebezpieczną wartością wymuszoną
Word8
to 8-bitowa liczba bez znaku, która mieści się w zakresie od 0 do 255. Int8
to podpisany 8-bitowy numer w zakresie od -128..127.
Ponieważ oba są liczbami 8-bitowymi, zakładałem, że wymuszanie jednego na drugim będzie bezpieczne i po prostu zwrócę 8-bitowe wartości, tak jakby były podpisane/niepodpisane.
Na przykład: unsafeCoerce (-1 :: Int8) :: Word8
Spodziewam się uzyskać wartość Word8
z 255 (ponieważ reprezentacja bitowa -1 w podpisanym int jest taka sama jak 255 w unsigned int).
Jednak, kiedy zrobić wykonać zmusić The Word8
zachowanie jest dziwne:
> 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
Nie rozumiem jak show x
wraca "-1"
tutaj. Jeśli spojrzysz na map show [minBound..maxBound :: Word8]
, żadna z możliwych wartości dla Word8
nie zostanie znaleziona w "-1"
. Ponadto, w jaki sposób dodanie 0 do liczby zmienia zachowanie, nawet jeśli typ nie został zmieniony? O dziwo, wygląda na to, że dotyczy to tylko klasy Show
- moja klasa ShowType
zwraca poprawną wartość.
Wreszcie kod fromIntegral (-1 :: Int8) :: Word8
działa zgodnie z oczekiwaniami, a zwraca 255 i działa poprawnie z show
. Czy ten kod może zostać zredukowany do kompilacji przez kompilator?
Należy zauważyć, że to pytanie jest tylko z ciekawości, jak typy są reprezentowane w ghc na niskim poziomie. W rzeczywistości nie używam w moim kodzie niebezpiecznegoCo commerce.
Dzięki temu ma teraz sens! –