Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting between Word8 and Word16 in Haskell

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

I 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 getByte gets Byte number b from a number num. The function encodeWord16 uses this helper function to do the little endian conversion.

This however does not compile, I get the 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 (very unsystematically) tried to achieve the desired result by randomly distributing fromIntegral expressions, but obviously my understanding of the haskell type system is not good enough to solve this problem. Is there a systematic way to approach this problem? Basically I want the function encodeWord16 to have the type signature Word16 -> [Word8].

like image 664
Julian Avatar asked May 01 '14 16:05

Julian


1 Answers

fromIntegral can be used for conversion between various integral types.

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

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

It'd be nicer though to have getByte return Word8-s:

getByte :: Int -> Word16 -> Word8
getByte b num = fromIntegral $ shift (relevantBits b num) (shiftNum b)
    -- where ...
like image 118
András Kovács Avatar answered Dec 01 '22 12:12

András Kovács