{-# LANGUAGE ConstraintKinds #-}

{-# OPTIONS_GHC -Wall #-}

-- | Calculate incremental changes of data structures.
-- 
-- The 'Incremental' class provides a set of functions that work like the unix
-- utilities 'diff' and 'patch'.  'changes' generates an incremental diff between
-- two data values.  The incremental diff can then be applied by the
-- 'applyChanges' function.
--
-- The primary intention of this library is to support efficient serialization.
-- As such, default 'Increment' types are automatically provided with
-- 'Beamable' instances.
--
-- > {-# LANGUAGE DeriveGenerics #-}
-- > {-# LANGUAGE ConstraintKinds #-}
-- > {-# LANGUAGE FlexibleContexts #-}
-- > {-# LANGUAGE UndecidableInstances #-}
-- >
-- > import GHC.Generics
-- > import Data.Beamable
-- > import Data.ByteString as B
-- >
-- > data Foo a b = Foo Int (Maybe a) b deriving (Generic, Eq, Show)
-- >
-- > -- If a 'Generic' instance is available, the default definition is
-- > -- fine, after adding some constraints.
-- > instance (IncrementalCnstr a, IncrementalCnstr b) => Incremental (Foo a b)
-- >
-- > -- generate some test data
-- > foo1 = Foo 1 Nothing "foo1"
-- > foo2 = Foo 1 (Just "foo2") "foo1"
-- >
-- > -- the 'changes' function calculates an incremental changeset from
-- > -- 'foo1' to 'foo2'
-- > diff = changes foo1 foo2
-- >
-- > -- 'applyChanges' applies the changes in an incremental patch to some data
-- > -- applyChanges foo1 diff == foo2
-- > -- True
-- >
-- > -- incremental changes can be smaller (sometimes significantly smaller)
-- > -- than the data source
-- > -- B.length $ encode diff
-- > -- 8
-- > -- B.length $ encode foo2
-- > -- 12
-- 
-- Incremental changes are not in general commutative or optional, and
-- it can be an error to apply a change to a data structure that doesn't match
-- the originating structure.  For example:
--
-- > *Data.Increments> let diff = changes (Left 1) (Left 2 :: Either Int Char)
-- > *Data.Increments> applyChanges (Right 'a') diff
-- > *** Exception: Data.Increments: malformed Increment Rep
--
module Data.Increments (
  Incremental (..)
, Changed (..)
, IncrementalCnstr
) where

import Data.Increments.Containers  ()
import Data.Increments.Internal