diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
 
 ```haskell
     {-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}
-    import Data.Enumerable (Enumerable(..))
+    import Data.Enumerate (Enumerable(..))
     import Data.Generics (Generics)
 
     data CrudOp = Add | Edit | Delete | View
diff --git a/enumerate.cabal b/enumerate.cabal
--- a/enumerate.cabal
+++ b/enumerate.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                enumerate
-version:             0.1.0
+version:             0.1.1
 synopsis:            enumerate all the values in a finite type (automatically)
 description:         provides (1) a typeclass for enumerating all values in a finite type, (2) a generic instance for automatic deriving, and (3) helpers that reify functions (partial or total, monadic or pure) into a Map.
 
@@ -17,7 +17,6 @@
 extra-source-files:  README.md
 cabal-version:       >=1.10
 
-
 library
  exposed-modules:
   Data.Enumerate
@@ -29,6 +28,7 @@
   Data.Enumerate.Extra
   Data.Enumerate.Large
   Data.Enumerate.Function
+  Data.Enumerate.Enum
   -- Data.CoRec
   -- Data.CoRec.MemoTrie
   -- Data.TEnumerate
@@ -37,6 +37,7 @@
      base ==4.8.*
    , containers ==0.5.*
    , ghc-prim==0.4.*
+   , array ==0.5.*
 
    , semigroups ==0.18.*
    , exceptions ==0.8.*
@@ -52,7 +53,7 @@
  default-language:    Haskell2010
 
 
-executable example
+executable enumerate-example
 
  main-is:  Main.hs
  hs-source-dirs:      .
@@ -60,4 +61,4 @@
 
  build-depends:
      base >=4.8 && <4.9
-   , enumerate ==0.0.0
+   , enumerate
diff --git a/sources/Data/Enumerate.hs b/sources/Data/Enumerate.hs
--- a/sources/Data/Enumerate.hs
+++ b/sources/Data/Enumerate.hs
@@ -1,23 +1,27 @@
-{-| see "Data.Enumerable.Types" for detailed documentation. 
+{-| see "Data.Enumerable.Types" for detailed documentation.
 
 to import every symbol in this package, run this in GHCi:
 
 @
-:m +  Data.Enumerate  Data.Enumerate.Extra  Data.Enumerate.Large  Data.Enumerate.Function 
+:m +  Data.Enumerate  Data.Enumerate.Extra  Data.Enumerate.Large  Data.Enumerate.Function
 @
 
-the modules "Data.Enumerate.Large" and "Data.Enumerate.Function" have orphan instances for large types, 
-and aren't reexported by default. 
-this makes attempting to enumerate them a type error, rather than runtime non-termination. 
+the modules "Data.Enumerate.Large" and "Data.Enumerate.Function" have orphan instances for large types,
+and aren't reexported by default.
+this makes attempting to enumerate them a type error, rather than runtime non-termination.
 
+See the source of "Data.Enumerate.Example" for an example.
+
 -}
-module Data.Enumerate
+module Data.Enumerate --TODO rename to Enumerable
  ( module Data.Enumerate.Types
  , module Data.Enumerate.Reify
- -- , module Data.Enumerate.Domain 
- , module Data.Enumerate.Map 
- ) where 
+ -- , module Data.Enumerate.Domain
+ , module Data.Enumerate.Map
+ , module Data.Enumerate.Enum
+ ) where
 import Data.Enumerate.Types
 import Data.Enumerate.Reify
 -- import Data.Enumerate.Domain
 import Data.Enumerate.Map
+import Data.Enumerate.Enum
diff --git a/sources/Data/Enumerate/Enum.hs b/sources/Data/Enumerate/Enum.hs
new file mode 100644
--- /dev/null
+++ b/sources/Data/Enumerate/Enum.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-|
+
+usage:
+
+@
+data A = ...
+
+instance 'Bounded' A where
+ minBound = 'minBound_enumerable' array_A
+ maxBound = 'maxBound_enumerable' array_A
+
+instance 'Enum' A where
+ toEnum   = 'toEnum_enumerable'   array_A
+ fromEnum = 'fromEnum_enumerable' table_A
+
+-- CAF
+array_A :: 'Array' Int A
+array_A = 'array_enumerable'
+
+-- CAF
+table_A :: 'Map' A Int
+table_A = 'table_enumerable'
+
+-- we must pass in <https://wiki.haskell.org/Constant_applicative_form CAF>s
+-- (i.e. expressions that are top-level and unconstrained),
+-- which will be shared between all calls to minBound/maxBound/toEnum/fromEnum.
+-- TODO must we?
+@
+
+--TODO template-haskell
+
+(also see the source of "Data.Enumerate.Example")
+
+-}
+module Data.Enumerate.Enum
+ ( minBound_enumerable
+ , maxBound_enumerable
+
+ , toEnum_enumerable
+ , fromEnum_enumerable
+
+ , array_enumerable
+ , table_enumerable
+ ) where
+
+import Data.Enumerate.Types
+
+import Numeric.Natural
+import qualified Data.Array as Array
+import Data.Array (Array, (!))
+import qualified Data.Map as Map
+import Data.Map (Map)
+
+
+minBound_enumerable :: forall a. (Enumerable a) => Array Int a -> a
+minBound_enumerable as = (as ! 0) --TODO safe get:  (__fromJust__ "minBound")
+{-# INLINE minBound_enumerable #-}
+
+maxBound_enumerable :: forall a. (Enumerable a) => Array Int a -> a
+maxBound_enumerable as = (as ! (n-1)) --TODO safe get:  (__fromJust__ "maxBound")
+ where n = nat2int $ cardinality ([] :: [a])
+{-# INLINE maxBound_enumerable #-}
+
+
+toEnum_enumerable :: forall a. (Enumerable a) => Array Int a -> (Int -> a)
+toEnum_enumerable as = \i -> (as ! i) -- i.e. (!) --TODO safe get:  (__fromJust__ "toEnum")
+{-# INLINE toEnum_enumerable #-}
+
+fromEnum_enumerable :: forall a. (Enumerable a, Ord a) => Map a Int -> (a -> Int)
+fromEnum_enumerable as = \x -> (__fromJust__ "fromEnum") (Map.lookup x as)
+{-# INLINE fromEnum_enumerable #-}
+
+
+--TODO Nat ==> Int
+array_enumerable :: forall a. (Enumerable a) => Array Int a --TODO
+array_enumerable = Array.listArray (0, n - 1) enumerated --TODO is array efficient?
+ where n = nat2int $ cardinality ([] :: [a])
+
+table_enumerable :: forall a. (Enumerable a, Ord a) => Map a Int
+table_enumerable = Map.fromList (zip enumerated [0 .. n - 1])
+ where n = nat2int $ cardinality ([] :: [a])
+
+
+__fromJust__ :: String -> Maybe a -> a
+__fromJust__ name = maybe (__bug__ name) id
+
+__bug__ :: String -> a
+__bug__ name = error (name ++ ": invalid Enumerable instance")
+--TODO print typerep; add constraint, all types are Typeable
+
+nat2int :: Natural -> Int
+nat2int = fromInteger . fromIntegral
diff --git a/sources/Data/Enumerate/Example.hs b/sources/Data/Enumerate/Example.hs
--- a/sources/Data/Enumerate/Example.hs
+++ b/sources/Data/Enumerate/Example.hs
@@ -1,18 +1,32 @@
 {-# LANGUAGE LambdaCase, DeriveGeneric, DeriveAnyClass #-}
+{-# LANGUAGE FlexibleInstances #-}
 module Data.Enumerate.Example where
 import Data.Enumerate
 
-import           System.Environment             (getArgs)
+import Data.Array (Array)
+import Data.Map (Map)
+
+--import           System.Environment             (getArgs)
 import           Data.Void (Void)
 import           GHC.Generics (Generic)
 
 
-main = mainWith =<< getArgs
+-- main = mainWith =<< getArgs
+--
+-- mainWith = \case
+--  _ -> do
 
-mainWith = \case
- _ -> traverse print demoEnumerated
+main = do
+    putStrLn ""
+    traverse print demoEnumerated
 
+    putStrLn ""
+    print $ (minBound :: Demo Bool)
+    print $ (maxBound :: Demo Bool)
 
+    putStrLn ""
+    print $ demoEnumerated == [minBound..maxBound]
+
 {- | (for documentation)
 
 demonstrates: empty type, unit type, product type, sum type, type variable.
@@ -20,32 +34,48 @@
 with @\{\-\# LANGUAGE DeriveGeneric, DeriveAnyClass \#\-\}@, the derivation is a one-liner:
 
 @
-data DemoEnumerable a = ... deriving (Show,Generic,Enumerable)
+data Demo a = ... deriving (Show,Generic,Enumerable)
 @
 
 -}
-data DemoEnumerable a
- = DemoEnumerable0 Void
- | DemoEnumerable1
- | DemoEnumerable2 Bool (Maybe Bool)
- | DemoEnumerable3 a
- deriving (Show,Generic,Enumerable)
+data Demo a
+ = Demo0 Void
+ | Demo1
+ | Demo2 Bool (Maybe Bool)
+ | Demo3 a
+ deriving (Show,Eq,Ord,Generic,Enumerable)
 
 {- | (for documentation)
 
 @demoEnumerated = enumerated@
 
 >>> traverse print demoEnumerated
-DemoEnumerable1
-DemoEnumerable2 False Nothing
-DemoEnumerable2 False (Just False)
-DemoEnumerable2 False (Just True)
-DemoEnumerable2 True Nothing
-DemoEnumerable2 True (Just False)
-DemoEnumerable2 True (Just True)
-DemoEnumerable3 False
-DemoEnumerable3 True
+Demo1
+Demo2 False Nothing
+Demo2 False (Just False)
+Demo2 False (Just True)
+Demo2 True Nothing
+Demo2 True (Just False)
+Demo2 True (Just True)
+Demo3 False
+Demo3 True
 
 -}
-demoEnumerated :: [DemoEnumerable Bool]
+demoEnumerated :: [Demo Bool]
 demoEnumerated = enumerated
+
+instance Bounded (Demo Bool) where
+ minBound = minBound_enumerable array_DemoBool
+ maxBound = maxBound_enumerable array_DemoBool
+
+instance Enum (Demo Bool) where
+ toEnum   = toEnum_enumerable   array_DemoBool
+ fromEnum = fromEnum_enumerable table_DemoBool
+
+-- CAF
+array_DemoBool :: Array Int (Demo Bool)
+array_DemoBool = array_enumerable
+
+-- CAF
+table_DemoBool :: Map (Demo Bool) Int
+table_DemoBool = table_enumerable
