-- automaticke odvozovani instanci
import Generics

class MyEq t where
  myEq::t->t->Bool
  myEq {| Unit |} Unit Unit = True
  myEq {| a :+: b |} (Inl x1) (Inl x2) = x1 `myEq` x2
  myEq {| a :+: b |} (Inr x1) (Inr x2) = x1 `myEq` x2
  myEq {| a :+: b |} _ _ = False
  myEq {| a :*: b |} (x1 :*: y1) (x2 :*: y2) = (x1 `myEq` x2) && (y1 `myEq` y2)

instance MyEq Int where
  myEq x y = x == y
instance MyEq Bool where
  myEq x y = x == y
instance MyEq a => MyEq [a]

class Bin a where
    toBin   :: a -> [Int]
    fromBin :: [Int] -> (a, [Int])
  
    toBin {| Unit |}    Unit	  = []
    toBin {| a :+: b |} (Inl x)   = 0 : toBin x
    toBin {| a :+: b |} (Inr y)   = 1 : toBin y
    toBin {| a :*: b |} (x :*: y) = toBin x ++ toBin y
  
    fromBin {| Unit |}    bs      = (Unit, bs)
    fromBin {| a :+: b |} (0:bs)  = (Inl x, bs')    where (x,bs') = fromBin bs
    fromBin {| a :+: b |} (1:bs)  = (Inr y, bs')    where (y,bs') = fromBin bs
    fromBin {| a :*: b |} bs	  = (x :*: y, bs'') where (x,bs' ) = fromBin bs
							  (y,bs'') = fromBin bs'

instance Bin Int where
  toBin 0 = [1,0]
  toBin x = d : d : toBin (x `div` 2)
    where d = x `mod` 2
  fromBin (1:0:rest) = (0,rest)
  fromBin (x:_:rest) = (2 * n + x, r)
    where
      (n, r) = fromBin rest

instance Bin a => Bin [a]
