{-# LANGUAGE FlexibleInstances, TemplateHaskell, CPP, Rank2Types, TypeOperators, TypeFamilies, FlexibleContexts, UndecidableInstances #-}

module Data.TrieMap.Class.Instances where

import Data.TrieMap.Class
import Data.TrieMap.TrieKey
import Data.TrieMap.Rep
import Data.TrieMap.Rep.TH
import Data.TrieMap.Rep.Instances
import Data.TrieMap.Sized
import Data.TrieMap.RadixTrie()
import Data.TrieMap.MultiRec.Instances
import Data.TrieMap.IntMap
import Data.TrieMap.OrdMap
import Data.TrieMap.ReverseMap
import Data.TrieMap.ProdMap
import Data.TrieMap.UnionMap
import Data.TrieMap.Class
import Data.TrieMap.Modifiers
import Data.TrieMap.Regular.Base
import Data.TrieMap.Regular.Class
import Data.TrieMap.Regular.Instances
-- import Data.TrieMap.UnionMap()
import Data.TrieMap.UnitMap()
import Data.TrieMap.Key

import Data.Bits
import Data.Char
import Data.Complex
import Data.Either
import Data.Foldable
import Data.Int 
import Data.List hiding (foldr)
import Data.Word
import Data.Array.IArray
import Data.Map(Map)
import Data.Set(Set)

import Prelude hiding (foldr)

#if __GLASGOW_HASKELL__
import GHC.Exts (build)
#else

build :: (forall b . (a -> b -> b) -> b -> b) -> [a]
build f = f (:) []
#endif
{-
instance TKey k => TKey [k] where
	type Rep [k] = L I0 (Rep k)
	toRep = map toRep
	fromRep = map fromRep-}

-- instance TKey Int
-- instance TKey Double
-- instance TKey Char
-- instance TKey Bool
-- instance TKey Word
-- instance TKey Int32
-- instance TKey Word32
-- instance TKey Word16
-- instance TKey Word8
-- instance TKey Int8
-- instance TKey Int16
-- instance TKey Word64
-- instance TKey Int64
-- instance TKey ()
-- instance TKey a => TKeyT ((,) a)
-- instance (TKey a, TKey b) => TKey (a, b)
-- instance (TKey a, TKey b) => TKeyT ((,,) a b)
-- instance (TKey a, TKey b, TKey c) => TKey (a, b, c)
-- instance (TKey a, TKey b, TKey c) => TKeyT ((,,,) a b c)
-- instance (TKey a, TKey b, TKey c, TKey d) => TKey (a, b, c, d)
-- instance TKey a => TKey (I0 a)
-- instance TKeyT I0
-- instance TKey (U0 a)
-- instance TKeyT U0
-- instance TKey a => TKey (K0 a b)
-- instance TKey a => TKeyT (K0 a)
-- instance TKeyT f => TKeyT (L f)
-- instance (TKeyT f, TKey a) => TKey (L f a)
-- instance (Functor f, TKeyT f, TKeyT g) => TKeyT (f `O` g)
-- instance (TKeyT f, TKeyT g, TKey a) => TKey ((f `O` g) a)
-- instance (TKeyT f, TKeyT g) => TKeyT (f :*: g)
-- instance (TKeyT f, TKeyT g, TKey a) => TKey ((f :*: g) a)
-- instance (TKey a, TKey b) => TKey (Either a b)
-- instance TKey a => TKeyT (Either a)
-- instance TKey a => TKey [a]
-- instance TKeyT []
-- instance TKey a => TKey (Maybe a)
-- instance TKeyT Maybe
-- instance (TKey k, TKey a) => TKey (TMap k a)
-- instance TKey k => TKeyT (TMap k)
-- instance TKeyT Set
-- instance TKeyT Rev
-- instance TKey a => TKey (Rev a)
-- instance TKey a => TKey (Set a)
-- instance TKey k => TKeyT (Map k)
-- instance (TKey k, TKey a) => TKey (Map k a)
-- instance (TKey i, Ix i) => TKeyT (Array i)
-- instance (TKey i, Ix i, TKey e) => TKey (Array i e)

type instance RepT (TMap k) = L (K0 (Rep k) :*: I0)
type instance Rep (TMap k a) = RepT (TMap k) (Rep a)

-- instance (Repr k, TrieKey (Rep k) (TrieMap (Rep k))) => TKey k
-- instance (ReprT f, TrieKeyT (RepT f) (TrieMapT (RepT f))) => TKeyT f

instance TKey k => ReprT (TMap k) where
	toRepTMap f (TMap m) = List (foldWithKeyM (\ k (Elem a) xs -> (K0 k :*: I0 (f a)):xs) m [])
	fromRepTMap f (List xs) = TMap (fromDistAscListM (const 1) [(k, Elem (f a)) | (K0 k :*: I0 a) <- xs])
{-
instance (TKey k, Repr a) => Repr (TMap k a) where
	toRep = toRepTMap toRep
	fromRep = fromRepTMap fromRep-}