-import Data.Bits (Bits, testBit, bitSize, shiftR, isSigned)

+import Data.Bits (FiniteBits, Bits, testBit, finiteBitSize, bitSizeMaybe, shiftR, isSigned)

boolXOR :: Bool -> Bool -> Bool

boolXOR p q = (p && not q) || (not p && q)

-- | Convert a number to a list of bits in usual binary encoding (most

-- significant bit last). Truncates unset major bits.

--- This function is undefined for negative numbers of types that do not

--- have fixed bitsize, like 'Integer'.

+-- The function may be also applied to unbounded integral types (like

+-- 'Integer'): it will return a list of bits for positive values, and

+-- an empty list for negative values or zero.

toList :: (Bits b, Num b) => b -> [Bool]

- | isSigned i && signum i == (-1) =

- let b = map not . toList $ negate i - 1

- in b ++ (take (bitSize i - length b) $ repeat True) -- pad major bits

+ let mbSize = bitSizeMaybe i

+ isNegative = isSigned i && signum i == (-1)

+ in case (mbSize, isNegative) of

+ (Just _, False) -> positiveToList i

+ (Just size, True) -> negativeToList size i

+ (Nothing, False) -> positiveToList i

let rest = toList $ shiftR i 1 -- works only for positive i

+ negativeToList bsize i =

+ let b = map not . toList $ negate i - 1

+ in b ++ (take (bsize - length b) $ repeat True)

-- | Convert a number to a list of bits in usual binary encoding (most

-- significant bit last).

-- Like 'toList', but returns all unset major bits too. So the length

--- of the output is always the same length as @bitSize i@.

-toList' :: (Bits b, Num b) => b -> [Bool]

-toList' i = map (testBit i) [0..bitSize i - 1]

+-- of the output is always the same length as @finiteBitSize i@.

+toList' :: (FiniteBits b, Num b) => b -> [Bool]

+toList' i = map (testBit i) [0..finiteBitSize i - 1]

-- | Convert a list of bits in binary encoding to a number.

fromList :: (Bits b, Num b) => [Bool] -> b