Library for binary

From HaskellWiki

The following is a library I often use for any processing that involves binary. (E.g., addresses on binary trees, compression algorithms, etc.) It defines the types Bit, Bits = [Bit], and various conversion functions.

This code is provided in case somebody finds it useful/interesting/amusing. Feel free to hack it to bits. (Get it? Sorry...)

module Bits where

import Data.List (foldl', unfoldr)

data Bit = Zero | One deriving (Eq)

instance Show Bit where
  showsPrec _ (Zero) = ("+0+"++)
  showsPrec _ (One)  = ("+1+"++)
  showList ls st = "*" ++ map bit_to_character ls ++ "*" ++ st

bit_to_integer :: (Integral i) => Bit -> i
bit_to_integer Zero = 0
bit_to_integer One  = 1

bit_to_boolean = (One ==)

bit_to_character Zero = '0'
bit_to_character One  = '1'

bit_from_integer :: (Integral i) => i -> Bit
bit_from_integer 0 = Zero
bit_from_integer 1 = One
bit_from_integer _ = error "bit_from_integer: Invalid integer."

bit_from_boolean b = if b then One else Zero

bit_from_character '0' = Zero
bit_from_character '1' = One
bit_from_character _   = error "bit_from_character: Invalid character."


type Bits = [Bit]

bits_trim  = dropWhile (Zero ==)
bits_pad n = reverse . take n . (++ repeat Zero) . reverse

bits_to_string   = map bit_to_character
bits_from_string = map bit_from_character

bits_from_integer :: (Integral i) => i -> Bits
bits_from_integer = reverse . unfoldr (\n -> if n == 0 then Nothing else Just (bit_from_integer $ n `mod` 2, n `div` 2)) . positive

bits_to_integer :: (Integral i) => Bits -> i
bits_to_integer = foldl' (\n b -> 2*n + bit_to_integer b) 0

bits_inc  = reverse . work . reverse where   -- Next binary integer
  work [] = [One]
  work (Zero : bs) = One  : bs
  work (One  : bs) = Zero : (work bs)

bits_next = reverse . work . reverse where   -- Next (balanced) tree address
  work [] = [Zero]
  work (Zero : bs) = One  : bs
  work (One  : bs) = Zero : (work bs)


positive n = if n < 0 then error "Negative argument." else n

Perhaps the functions bits_inc and bits_next require some explanation...

> take 9 $ iterate bits_inc []
[**,*1*,*10*,*11*,*100*,*101*,*110*,*111*,*1000*]

> take 9 $ iterate bits_next []
[**,*0*,*1*,*00*,*01*,*10*,*11*,*000*,*001*]