Convert between Word8 and Word16 in Haskell

I am trying to convert little endian to haskell so that I can turn Word16 into two Word8 (for example, 258 = 1 * 256 + 2, so the result should be [2, 1]). Then I pack the result into a byte string.

I have created the following code for this purpose:

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

The function getBytegets the number of bytes bfrom a number num. The function encodeWord16uses this helper function to convert the small end.

This, however, does not compile, I get an error:

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

I ( ) fromIntegral, , , haskell . ? , , encodeWord16 Word16 -> [Word8].

+4
4

? :

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 ]
+2

fromIntegral .

fromIntegral :: (Num b, Integral a) => a -> b

encodeWord16 :: Word16 -> [Word8]
encodeWord16 x = map fromIntegral [getByte 1 x, getByte 2 x]

getByte return Word8 -s:

getByte :: Int -> Word16 -> Word8
getByte b num = fromIntegral $ shift (relevantBits b num) (shiftNum b)
    -- where ...
+7

, , .

import Data.Word
import Data.ByteString.Builder
import Data.ByteString.Lazy (unpack)

encodeWord16 :: Word16 -> [Word8]
encodeWord16 = unpack . toLazyByteString . word16LE
+2

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#ghaps )

So you can just use it like this:

> 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
+1
source

Source: https://habr.com/ru/post/1538884/


All Articles