-- | Anexperimental feature to override the 'Enumerable' instance for any type.

module Test.Feat.Class.Override (
  Override,
  noOverride,
  addOverride,
  override
  ) where

import Test.Feat.Enumerate
import Test.Feat.Class
import Test.Feat.Internals.Tag(Tag(Class))
import Test.Feat.Modifiers
import Control.Monad.TagShare
import Control.Monad.State

type Override = DynMap Tag

noOverride :: Override
noOverride  = dynEmpty

addOverride :: Enumerable a => Enumerate a -> Override -> Override
addOverride = dynInsert Class

-- | This function is best described with an example:
-- 
--  @
--    let e1 = override $ addOverride (unary 'printable') noOverride :: Enumerate T
--  @
-- 
-- @e1@ enumerates values of type @T@ where all characters (accessed using 
-- the @Enumerable@ instance for @Char@) are printable. Sometimes this can save 
-- you from placing lots of 'printable' modifiers in your instances or 
-- newtypes in your data type definitions.
--
-- This works for any type (not just characters) as long as the instance does 
-- not override the default definition of 'shared' so it does not use 
-- 'tagShare' (no instance in the library does this).This function should not 
-- be used for defining instances (doing so might increase memory usage).
override :: Enumerable a => Override -> Enumerate a
override = evalState (optimal shared)