
OK, I have a situation....I have a little PIC microchip sending out 24 bit ADC values over TCP/IP... I want to know what is the nicest / cleanest / best / efficient / geekiest etc way tyo convert the three bytes it sends into an unsigned 24-bit number... main :: IO () main = do h

While I like your pre-zipping solution, I see why it didn't work out
well for you. The way that I've done such things is with folds. The
thing is that you need to store both the final answer as well as the
index of the bytestring where you are so that the supplied function
can know what power to take 256 to at each step. Here's how I would
do it.
totalBS :: ByteString -> Integer
totalBS bs = ans
where
(_,ans) = foldr' func (0,0) (BS.reverse bs)
func byte (acc,ans) = (acc+1, ans + fromIntegral byte * (256^acc))
This should work on any size bytestring.
On Tue, Mar 6, 2012 at 11:20 AM, Emacs The Viking
OK, I have a situation....I have a little PIC microchip sending out 24 bit ADC values over TCP/IP... I want to know what is the nicest / cleanest / best / efficient / geekiest etc way tyo convert the three bytes it sends into an unsigned 24-bit number...
main :: IO ()
main = do
h <- connectTo "picbox" (PortNumber 20000)
len <- liftM unpack $ BS.hGet h 3
hClose h
print len
that currently gives me [17,0,0] on the console, which is 0x000011 in hex.
I have played with ByteString foldl' and all sorts of other ways to do what I want, which is essentially the sum of b0 + (b1*256) + (b2 * 256 * 256) where b0 is 17 and b2 and b3 are the zeros.
I've tried toying with zipping it with an array containing [1, 256, 256*256], I've tried using left and right folds and pre-multiplying the accumulator by 256 each time but the ByteString seems limited to 0-255 and so it doesn't work. I've tried brute force arithmetic by extracting each part and doing the maths etc.
The challenge then is to show me how to deal with ByteStrings and "fromIntegral" type conversions; I am still learning Haskell and loving it but things like this really stump me sometimes! LOL
The generalisation I guess is how to convert an array of bytes into a number where each byte must be multiplied by its respective power... I am still working on it myself... I am still happy that I used "liftM" for the first time and actually understood why, how and what I was doing it for LMAO
Thanks... I have a feeling the answers will really help me.
Sean Charles.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Tue, Mar 6, 2012 at 7:47 PM, David McBride
While I like your pre-zipping solution, I see why it didn't work out well for you. The way that I've done such things is with folds. The thing is that you need to store both the final answer as well as the index of the bytestring where you are so that the supplied function can know what power to take 256 to at each step. Here's how I would do it.
totalBS :: ByteString -> Integer totalBS bs = ans where (_,ans) = foldr' func (0,0) (BS.reverse bs) func byte (acc,ans) = (acc+1, ans + fromIntegral byte * (256^acc))
This should work on any size bytestring.
Rather than doing this you can simply multiply by 256 because a + 256 b + 256² c == a + 256 ( b + 256 c ) So :
totalBS :: ByteString -> Integer totalBS = BS.foldr' (\byte total -> fromIntegral byte + 256 * total) 0
This is an idiom often used :) Note that for normal sized words and if your parser become more complicated, you should look at the binary package to parse streams of bytes. -- Jedaï
participants (3)
-
Chaddaï Fouché
-
David McBride
-
Emacs The Viking