将Int转换为[Bool]表示的位列表

时间:2015-02-15 02:12:26

标签: haskell bit-manipulation

我知道使用Data.Bits我可以对Bits的实例进行逐位操作。然而,这不是我想要的。我明确地想要操作一个Bool列表,它代表每个位索引的位值。

更准确地说,我想操纵1字节整数的位。

我已设法使用map / testBitfoldl' / setBit将其投放使用。您可以在下面的ghci中看到我的测试:

λ import Data.Bits
λ import Data.List

λ let convertToBits :: Int -> [Bool] ; convertToBits x = map (testBit x) [7,6..0]

λ let convertFromBits :: [Bool] -> Int ; 
   convertFromBits bs = foldl' (\acc (i,b) -> if b then setBit acc i else acc) 0 $ zip [7,6..0] bs

λ convertToBits 255
[True,True,True,True,True,True,True,True]

λ convertToBits 2
[False,False,False,False,False,False,True,False]

λ convertFromBits [False,False,False,True,True,False,False,True]
25

λ convertFromBits $ convertToBits 255
255

λ convertFromBits $ convertToBits 10
10

然而,这并不是一个特别好的实现。我想知道这个(或类似的东西)是否可能出现在标准库中?

编辑------

快速的最后一点,即使我已经回答了下面的问题,我想我会增加一点,以防万一有人偶然发现并知道更好的答案。我将存储UArray中的所有位,这将比特包装Bool值。

在考虑它时,真正好的是将Word8转换为UArray ix Bool的函数。我想有一些有效/简单的方法可以做到这一点,但我不太了解低级别的东西来解决它。

2 个答案:

答案 0 :(得分:1)

以前是我的问题中的编辑。我还是想知道是否还有更好的东西。我正在想象一些字面上将Word8强制转换为其组成部分的数组,但也许这有点高尚......

bitwise,它使用bitshifting for their fromList function执行与我自己类似的实现。代替更好的主意,这表明使用Data.Bits结合某种map和某种fold是规范解决方案:

-- | Convert a little-endian list of bits to 'Bits'.
{-# INLINE fromListLE #-}
fromListLE :: (Num b, Bits b) => [Bool] {- ^ \[least significant bit, ..., most significant bit\] -} -> b
fromListLE = foldr f 0
  where
    f b i = fromBool b .|. (i `shiftL` 1)

-- | Convert a 'Bits' (with a defined 'bitSize') to a list of bits, in
--   little-endian order.
{-# INLINE toListLE #-}
toListLE :: (Num b, Bits b) => b -> [Bool] {- ^ \[least significant bit, ..., most significant bit\] -}
toListLE b = P.map (testBit b) [0 .. bitSize b - 1]

答案 1 :(得分:0)

这尚未经过全面测试,但它是本机实施的提案。

toBitsBySize :: Int -> Int -> [Bool]
toBitsBySize  0 x = []
toBitsBySize sz 0 = [False | i <- [1..sz]]
toBitsBySize sz x =  if k == 0 
    then False : (toBitsBySize n x) 
    else True  : (toBitsBySize n (x - k*m))
    where n = sz - 1
          m = 2^n
          k = x `div` m

toBits8 = toBitsBySize 8

一些例子:

*Main> toBits8 2
[False,False,False,False,False,False,True,False]
*Main> toBits8 255
[True,True,True,True,True,True,True,True]
*Main> toBits8 129
[True,False,False,False,False,False,False,True]