
Thanks - I thought there would be some api for it but I see it's pretty
simple to do on your own.
I came up with this (dealing with non-multiple of 8 numbers of bits)
bitsToBytes :: [Bool] -> [Word8]
bitsToBytes [] = []
bitsToBytes bits = map bitsToByte (getChunks bits)
where bitsToByte = foldl' (\byte bit -> byte*2 + if bit then 1 else 0) 0
getChunks :: [Bool] -> [[Bool]]
getChunks [] = []
getChunks xs
| length xs < 8 = getChunks $ take 8 (xs ++ repeat False)
| otherwise =
let (these,rest) = splitAt 8 xs
in these:getChunks rest
On Thu, Sep 2, 2010 at 3:18 AM, David Virebayre
wrote:
I could have been a bit more verbose.
The way I see it, since you have an arbitrary long list of 'bits' that you want to convert into bytes, the first thing to do is to group this list into sublists of 8 bits.
That's what chunk does: it splits the list at the 8th element, and recursively does it for the rest of the list, until the list is empty.
One problem with that is that if the length of the list isn't a multiple of 8, then the last byte might be incorrect.
chunk :: [Bool] -> [[ Bool ]] chunk [] = [] chunk l = a : chunk b where (a,b) = splitAt 8 l
This one converts a list of 'bits' into a number. The head of the list is assumed to be the most significant bit :
conv1 = foldl' (\a b -> a*2 + if b then 1 else 0) 0
if we want the head of the list to be the least significant bit, then you can convert with foldr :
conv1' = foldr (\b a -> a*2 + if b then 1 else 0) 0
Now converting the whole list is just a matter converting the whole list in groups, then converting each group :
convlist = map conv1 . chunk
test = convlist (replicate 8 True ++ replicate 8 False :: [Bool] )
David.