![](/img/trans.png)
[英]How to use Haskell's bitwise functions on unsigned types (e.g., `Word8`, `Word16`)?
[英]Converting between Word8 and Word16 in Haskell
我試圖在haskell中進行小端轉換,以便我可以將Word16轉換為兩個Word8(例如258 = 1 * 256 + 2,因此結果應為[2,1])。 然后我將結果打包成ByteString。
我為此創建了以下代碼:
import Data.Word
import Data.Bits
getByte b num = shift (relevantBits b num) (shiftNum b)
where bitMask b = sum $ map (2^) [8*b-8 .. 8*b-1]
relevantBits b num = num .&. bitMask b
shiftNum b = 8-8*b
encodeWord16 x = [getByte 1 x, getByte 2 x]
input :: Word16
input = 355
output :: [Word8]
output = encodeWord16 input
函數getByte
從數字num
獲取字節數b
。 函數encodeWord16
使用這個輔助函數來進行小端轉換。
但是這不能編譯,我得到錯誤:
Couldn't match expected type `Word8' with actual type `Word16'
In the first argument of `encodeWord16', namely `input'
In the expression: encodeWord16 input
In an equation for `output': output = encodeWord16 input
我(非常不系統地)嘗試通過隨機分布來自fromIntegral
表達式來實現期望的結果,但顯然我對haskell類型系統的理解不足以解決這個問題。 有沒有系統的方法來解決這個問題? 基本上我希望函數encodeWord16
具有類型簽名Word16 -> [Word8]
。
fromIntegral
可用於各種整數類型之間的轉換。
fromIntegral :: (Num b, Integral a) => a -> b
encodeWord16 :: Word16 -> [Word8]
encodeWord16 x = map fromIntegral [getByte 1 x, getByte 2 x]
讓getByte
返回Word8
-s會更好:
getByte :: Int -> Word16 -> Word8
getByte b num = fromIntegral $ shift (relevantBits b num) (shiftNum b)
-- where ...
您可能希望使用預定義的函數來執行此操作,而不是手動編碼轉換。
import Data.Word
import Data.ByteString.Builder
import Data.ByteString.Lazy (unpack)
encodeWord16 :: Word16 -> [Word8]
encodeWord16 = unpack . toLazyByteString . word16LE
如何直接提取這些字節? 像這樣:
encodeWord16 x = [ x .&. 0xFF, (x .&. 0xFF00) `shiftR` 8 ]
如果你想要encodeWord16
的簽名是Word16 -> [Word8]
,那么在它之前添加map fromIntegral
,就像這樣:
encodeWord16 :: Word16 -> [Word8]
encodeWord16 x = map fromIntegral [ x .&. 0xFF, (x .&. 0xFF00) `shiftR` 8 ]
binary包含以下代碼:
-- Words16s are written as 2 bytes in big-endian (network) order
instance Binary Word16 where
put = putWord16be
( http://hackage.haskell.org/package/binary-0.7.1.0/docs/Data-Binary.html#g:1 )
-- | Write a Word16 in big endian format
putWord16be :: Word16 -> Builder
putWord16be w = writeN 2 $ \p -> do
poke p (fromIntegral (shiftr_w16 w 8) :: Word8)
poke (p `plusPtr` 1) (fromIntegral (w) :: Word8)
( http://hackage.haskell.org/package/binary-0.7.1.0/docs/Data-Binary-Builder.html#g:5 )
所以你可以像這樣使用它:
> encode (355 :: Word16)
"\SOHc"
> toLazyByteString $ putWord16be 355
"\SOHc"
> index (encode (355 :: Word16)) 0
1
> index (toLazyByteString $ putWord16be 355) 0
1
> index (encode (355 :: Word16)) 1
99
> index (toLazyByteString $ putWord16be 355) 1
99
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.