module UniqueLogic.ST.SystemLabel (
   -- * Preparation
   Variable,
   globalVariable,
   -- * Posing statements
   Sys.T,
   Sys.localVariable,
   Sys.constant,
   Sys.assignment2,
   Sys.assignment3,
   Sys.Apply, Sys.arg, Sys.runApply,
   -- * Solution
   solve,
   Sys.query,
   ) where

import qualified UniqueLogic.ST.System as Sys
import qualified UniqueLogic.ST.SystemLog as SysLog

import qualified Control.Monad.Trans.Writer as MW
import Control.Monad.Trans.Writer (Writer, )
import Control.Monad.ST (ST, )

import Data.Monoid (Monoid, )

import Prelude hiding (log, )


data Variable w s a =
   Variable
      (a -> Writer w a)
      (SysLog.Variable w s a)

instance Sys.Var Variable where
   plainVariable (Variable _ v) = v
   runApply f (Variable log v) = SysLog.runApply (fmap log f) v
   constant = fmap (Variable return) . SysLog.constant
   localVariable = fmap (Variable return) SysLog.localVariable


globalVariable :: (a -> MW.Writer w a) -> ST s (Variable w s a)
globalVariable log = fmap (Variable log) Sys.globalVariable


solve :: (Monoid w) => Sys.T w s a -> MW.WriterT w (ST s) a
solve = SysLog.solve