{-# LANGUAGE TypeFamilies #-}

-- |
-- Module      : OAlg.Data.Constructable
-- Description : constructing values
-- Copyright   : (c) Erich Gut
-- License     : BSD3
-- Maintainer  : zerich.gut@gmail.com
--
-- constructing values by there 'Form'..
module OAlg.Data.Constructable
  (
    -- * Constructable
    Constructable(..), cmap
    -- * Exposable
  , Exposable(..), restrict
    
  )
  where 


--------------------------------------------------------------------------------
-- Exposable -

-- | types with an associated /form/ type and a function 'form' which exposes its values
-- to its /form/.
class Exposable x where
  -- | the form.
  type Form x

  -- | the associated form.
  form :: x -> Form x

--------------------------------------------------------------------------------
-- restrict -

-- | restriction of a @f@ in @'Form' __x__ -> y@.
restrict :: Exposable x => (Form x -> y) -> x -> y
restrict :: forall x y. Exposable x => (Form x -> y) -> x -> y
restrict Form x -> y
f = Form x -> y
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x. Exposable x => x -> Form x
form

  
--------------------------------------------------------------------------------
-- Constructable -

-- | types with an associated /form/, which serves as a /blueprint/ to construct a
-- corresponding value.
--
-- A common setting for this structure is a module with a reducible type __@f@__
-- (see @'OAlg.Data.Reducible'@) with public constructors - which serves as a form to be
-- filled out - and in the same module a type @e@ with a private constructor - lets say
-- @E@ - to hold the 'OAlg.Data.Reducible.reduced' @f@. Than an implementation would be
--
-- > make f = E (reduce f)
--
-- and
--
-- > form (E f) = f
--
-- __Property__ Let __@x@__ be an instance of the class 'Constructable' than holds:
-- For all @x@ in __@x@__ holds: @'make' ('form' x) '==' x@.
class Exposable x => Constructable x where
  -- | constructor.
  make :: Form x -> x

--------------------------------------------------------------------------------
-- cmap -

-- | restriction of a @f@ in @'Form' __x__ -> 'Form' __y__@. 
cmap :: (Constructable x, Constructable y) => (Form x -> Form y) -> x -> y
cmap :: forall x y.
(Constructable x, Constructable y) =>
(Form x -> Form y) -> x -> y
cmap Form x -> Form y
f = forall x. Constructable x => Form x -> x
make forall b c a. (b -> c) -> (a -> b) -> a -> c
. Form x -> Form y
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x. Exposable x => x -> Form x
form