{-# LANGUAGE TypeFamilies, FlexibleContexts, TypeOperators #-}

-- The infamous encode example

module Encode
where

import Char

import Data.Generics.IG.Representable

type Bit = Int

class Encodable a where
  encode :: a -> [Bit]

instance Encodable Unit where
  encode = const []

instance Encodable Char where
  encode = encode . ord

instance Encodable Int where
  encode = take 32 . enc
    where
      enc x = x `mod` 2 : enc (x `div` 2)

instance (Encodable a, Encodable b) => Encodable (a :*: b) where
  encode (x :*: y) = encode x ++ encode y

instance (Encodable a, Encodable b) => Encodable (a :+: b) where
  encode (Inl x) = 0 : encode x
  encode (Inr y) = 1 : encode y

dft_encode :: (Representable a, Encodable (Repr a)) => a -> [Bit]
dft_encode = encode . toRepr

-- an exception
instance Encodable a => Encodable [a] where
  encode l = encode (length l) ++ concatMap encode l

-- using the default representation
instance Encodable a => Encodable (Maybe a) where
  encode = dft_encode

