{-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances, TypeOperators #-}

module Data.TrieMap.Regular.Eq where

import Data.TrieMap.Regular.Base
-- import Data.TrieMap.MultiRec.Base(Family(..))
-- import Data.TrieMap.MultiRec.Eq(HEq0(..))
import Data.TrieMap.Modifiers

class EqT f where
	eqT0 :: (a -> a -> Bool) -> f a -> f a -> Bool

eqT :: (EqT f, Eq a) => f a -> f a -> Bool
eqT = eqT0 (==)

-- instance EqT (Family phi) where
-- 	eqT0 (==) (F a) (F b) = a == b

instance Eq a => EqT (K0 a) where
	eqT0 _ (K0 a) (K0 b) = a == b

instance EqT I0 where
	eqT0 (==) (I0 a) (I0 b) = a == b

instance EqT [] where
	eqT0 (==) = eqT' where
		eqT' (a:as) (b:bs) = a == b && eqT' as bs
		eqT' [] [] = True

eqT' _ _ = False

instance (EqT f, EqT g) => EqT (f :*: g) where
	eqT0 (==) (x1 :*: y1) (x2 :*: y2) = eqT0 (==) x1 x2 && eqT0 (==) y1 y2

instance (EqT f, EqT g) => EqT (f :+: g) where
	eqT0 (==) a b = case (a, b) of
		(L a, L b) -> eqT0 (==) a b
		(R a, R b) -> eqT0 (==) a b
		_	   -> False

instance EqT U0 where
	eqT0 _ _ _ = True

instance EqT f => EqT (L f) where
	eqT0 (==) (List xs) (List ys) = eqT' xs ys where
		eqT0' = eqT0 (==)
		eqT' (a:as) (b:bs) = eqT0' a b && eqT' as bs
		eqT' [] [] = True
		eqT' _ _ = False

instance (Regular a, Functor (PF a), EqT (PF a)) => Eq (Reg a) where
	a == b = eqT (from' a) (from' b)

instance (EqT f, Eq r) => Eq (L f r) where
	(==) = eqT

instance (EqT f, EqT g, Eq r) => Eq ((f :*: g) r) where
	(==) = eqT

instance (EqT f, EqT g, Eq r) => Eq ((f :+: g) r) where
	(==) = eqT

instance (EqT f, EqT g) => EqT (f `O` g) where
	eqT0 (==) (O x) (O y) = eqT0 (eqT0 (==)) x y

instance (EqT f, EqT g, Eq r) => Eq ((f `O` g) r) where
	(==) = eqT

instance Eq a => Eq (K0 a r) where
	K0 a == K0 b = a == b

instance Eq r => Eq (I0 r) where
	I0 a == I0 b = a == b

instance Eq (U0 r) where
	_ == _ = True

instance Eq a => EqT ((,) a) where
	eqT0 (=#=) (a, b) (c, d) = a == c && b =#= d

instance Eq a => EqT (Either a) where
	eqT0 _ (Left a) (Left b) = a == b
	eqT0 (==) (Right a) (Right b) = a == b
	eqT0 _ _ _ = False

instance EqT Ordered where
	eqT0 (==) (Ord x) (Ord y) = x == y

instance EqT Rev where
	eqT0 (==) (Rev x) (Rev y) = y == x