{-# LANGUAGE TypeFamilies #-}
module Data.TrieMap.Representation.Class where

import Data.Vector

-- | The @Repr@ type class denotes that a type can be decomposed to a representation
-- built out of pieces for which the 'TrieKey' class defines a generalized trie structure.
-- It is required that, if @('Repr' a, 'Eq' a)@, and @x, y :: a@, then @x '==' y@
-- if and only if @'toRep' x '==' 'toRep' y@.  It is typically the case that
-- @'compare' x y == 'compare' ('toRep' x) ('toRep' y)@, as well, but this is not
-- strictly required.  (It is, however, the case for all instances built into the package.)
-- As an additional note, the 'Key' modifier is used for \"bootstrapping\" 'Repr' instances,
-- allowing a type to be used in its own 'Repr' definition when wrapped in a 'Key' modifier.
class Repr a where
  type Rep a
  type RepList a
  toRep :: a -> Rep a
  toRepList :: [a] -> RepList a

-- | A default implementation of @'RepList' a@.
type DRepList a = Vector (Rep a)

-- | A default implementation of 'toRepList'.
dToRepList :: Repr a => [a] -> DRepList a
dToRepList = fromList . Prelude.map toRep

-- | Uses the 'RepList' instance of @a@.  (This allows for efficient and automatic implementations of e.g. @Rep String@.)
instance Repr a => Repr [a] where
  type Rep [a] = RepList a
  type RepList [a] = Vector (RepList a)
  toRep = toRepList
  toRepList = dToRepList