packages feed

derive-IG-0.1.1: example/BinEncode.hs

{-# LANGUAGE TypeOperators, TypeFamilies, FlexibleContexts, EmptyDataDecls, TemplateHaskell #-}
module Main where
import Generics.Instant
import Data.List
import Generics.Instant.Derive

derive ''Either
deriveWith ''()   [Just "Unit_Unit"]
deriveWith ''(,,) [Just "Triple_Triple"]

class Bin a where
    toBin :: a -> [Int]
    fromBin :: [Int] -> (a, [Int])

instance Bin U where
    toBin   U  = []
    fromBin xs = (U, [])

instance (Bin a, Bin b) => Bin (a :+: b) where
    toBin (L a) = 0:toBin a
    toBin (R b) = 1:toBin b
    fromBin (0:bin) = let (a, bin') = fromBin bin in (L a, bin')
    fromBin (1:bin) = let (b, bin') = fromBin bin in (R b, bin')

instance (Bin a, Bin b) => Bin (a :*: b) where
    toBin (a :*: b) = toBin a ++ toBin b
    fromBin bin     =
      let (a, bin')  = fromBin bin
          (b, bin'') = fromBin bin'
      in (a :*: b, bin'')

instance Bin a => Bin (Rec a) where
    toBin (Rec r) = toBin r
    fromBin bin   = let (r, bin') = fromBin bin in (Rec r, bin')

instance Bin a => Bin (C c a) where
    toBin (C a)  = toBin a
    fromBin bin  = let (a, bin') = fromBin bin in (C a, bin')

instance Bin a => Bin (Var a) where
    toBin (Var a) = toBin a
    fromBin bin   = let (x, bin') = fromBin bin in (Var x, bin')

def_toBin :: (Representable a, Bin (Rep a)) => a -> [Int]
def_toBin = toBin . from

def_fromBin :: (Representable a, Bin (Rep a)) => [Int] -> (a, [Int])
def_fromBin bin = let (rep, bin') = fromBin bin in (to rep, bin')


instance Bin Int where
    toBin i   = let sign   = if i < 0 then 1 else 0
                    i'     = abs i
                    binary = toBits i'
                in take (bitCount + 1) (sign:binary ++ replicate bitCount 0)
    fromBin a = let (s:as, bs) = splitAt (1+bitCount) a
                    sign = [1, -1] !! s
                in (sign*fromBits as, bs)

instance Bin Char where
  toBin      = take 21 . (++replicate 21 0) . toBits . fromEnum
  fromBin bs = let (ch, bs') = splitAt 21 bs in (toEnum $ fromBits ch, bs')

instance Bin Bool where
  toBin True  = [1]
  toBin False = [0]
  fromBin (1:xs) = (True, xs)
  fromBin (0:xs) = (False, xs)

instance Bin () where { toBin = def_toBin; fromBin = def_fromBin }
instance Bin a => Bin [a] where { toBin = def_toBin; fromBin = def_fromBin }
instance Bin a => Bin (Maybe a) where { toBin = def_toBin; fromBin = def_fromBin }
instance (Bin a, Bin b) => Bin (Either a b) where { toBin = def_toBin; fromBin = def_fromBin }
instance (Bin a, Bin b) => Bin (a, b) where { toBin = def_toBin; fromBin = def_fromBin }
instance (Bin a, Bin b, Bin c) => Bin (a, b, c) where { toBin = def_toBin; fromBin = def_fromBin }

unfoldrStep :: (b -> Bool) -> (b -> a) -> (b -> b) -> b -> Maybe (a, b)
unfoldrStep p f g x | p x       = Nothing
                    | otherwise = Just (f x, g x)

newtype Wrap a = Wrap {unWrap :: a} deriving (Show, Eq, Ord)

bitCount = ceiling $ logBase 2 $ fromIntegral (maxBound::Int)
toBits   = unfoldr (unfoldrStep (==0) (`mod`2) (`div`2))
fromBits = foldr (\a b -> a+2*b) 0