-- |
-- This library provides facilities to get a representation data of a type, 
-- while traversing all the types it refers to down to the primitives. 
-- Thus it transitively captures all the types involved, 
-- which may even come from different libraries. 
-- 
-- The produced data structure is a graph, which has a 'Hashable' instance, 
-- so it can be used to perform the matching aswell. 
-- E.g., one can produce a \"version\" hash with it.
-- 
-- To provide support by this library for any type use the TemplateHaskell 
-- to 'derive' an instance of the 'TypeStructure' class like this:
-- 
-- > {-# LANGUAGE TemplateHaskell #-}
-- > 
-- > import qualified TypeStructure
-- > 
-- > data AnyData = A | B Int | C Char
-- > 
-- > TypeStructure.derive ''AnyData
-- 
-- Following is a GHCi session, showing, how the library is supposed to be used:
-- 
-- > λ>import TypeStructure 
-- 
-- Construction of the type structure representation graph: 
-- 
-- > λ>graph (undefined :: Int)
-- >
-- > ( 
-- >   Type_Con ("GHC.Types","Int"),
-- >   [
-- >     ( 
-- >       ("GHC.Types","Int"),
-- >       Declaration_ADT [] 
-- >         [
-- >           ("I#",[Type_Con ("GHC.Prim","Int#")])
-- >         ] 
-- >     ),
-- >     (
-- >       ("GHC.Prim","Int#"),
-- >       Declaration_Primitive
-- >     )
-- >   ]
-- > )
-- 
-- Graphs of different types are guaranteed to be different:
-- 
-- > λ>graph (undefined :: Int) /= graph (undefined :: Integer)
-- >
-- > True
-- 
-- Graphs of values of the same type are guaranteed to be the same:
-- 
-- > λ>graph True == graph False
-- >
-- > True    
-- 
-- Acquiring a hash of the typestructure:
-- 
-- > λ>import Data.Hashable
-- >
-- > λ>hash $ graph (undefined :: Int)
-- >
-- > 3224108341943761557
-- 
-- Hashes of different types should not be equal:
-- 
-- > λ>(hash $ graph (undefined :: Int)) /= (hash $ graph (undefined :: Integer))
-- >
-- > True
-- 
module TypeStructure
(
  -- * Class
  TypeStructure(..), 
  derive,
  -- * Model
  module TypeStructure.Model, 
)
where

import TypeStructure.Prelude.Basic
import TypeStructure.Prelude.Data
import TypeStructure.Prelude.Transformers
import TypeStructure.Model
import TypeStructure.Class
import TypeStructure.TH
import qualified TypeStructure.Prelude.TH as TH
import qualified GHC.Exts


-- base
---------------------
derive ''(->)
derive ''()
derive ''[]
derive ''Int
derive ''Int8
derive ''Int16
derive ''Int32
derive ''Int64
derive ''Integer
derive ''Word
derive ''Word8
derive ''Word16
derive ''Word32
derive ''Word64
derive ''Float
derive ''Double
derive ''Char
derive ''Bool
derive ''Ordering
derive ''Fixed
derive ''E0
derive ''E1
derive ''E2
derive ''E3
derive ''E6
derive ''E9
derive ''E12
derive ''Ratio
derive ''Last
derive ''First
derive ''Any
derive ''All
derive ''Sum
derive ''Product
derive ''Dual
derive ''Seq
derive ''Maybe
derive ''Either
derive ''GHC.Exts.Any
derive ''ThreadId
derive ''TypeRep
derive ''StableName

-- tuples
fmap join $ mapM derive $ map TH.tupleTypeName [2..24]

-- transformers
---------------------
derive ''Identity

-- vector
---------------------
derive ''Vector

-- array
---------------------
derive ''UArray
derive ''Array

-- containers
---------------------
derive ''IntSet
derive ''IntMap
derive ''Set
derive ''Tree
derive ''Map

-- unordered-containers
---------------------
derive ''HashSet
derive ''HashMap

-- bytestring
---------------------
derive ''ByteString
derive ''LazyByteString

-- text
---------------------
derive ''Text
derive ''LazyText

-- time
---------------------
derive ''AbsoluteTime
derive ''ZonedTime
derive ''LocalTime
derive ''TimeZone
derive ''TimeOfDay
derive ''NominalDiffTime
derive ''UTCTime
derive ''UniversalTime
derive ''DiffTime
derive ''Day

-- type-structure
---------------------
derive ''Type
derive ''Declaration