module UniqueLogic.ST.System ( -- * Preparation Var, Variable, Sys.globalVariable, plainVariable, -- * Posing statements T, localVariable, constant, assignment2, assignment3, Sys.Apply, arg, runApply, -- * Solution solve, query, ) where import qualified UniqueLogic.ST.SystemLog as Sys import UniqueLogic.ST.SystemLog (T, Variable) import qualified Control.Monad.Trans.Writer as MW import Control.Applicative (liftA, liftA2, ) import Control.Monad.ST (ST, ) import Data.Monoid (Monoid, ) class Var var where plainVariable :: var w s a -> Variable w s a runApply :: Monoid w => Sys.Apply w s a -> var w s a -> T w s () constant :: (Monoid w) => a -> T w s (var w s a) localVariable :: (Monoid w) => T w s (var w s a) instance Var Variable where plainVariable = id runApply f = Sys.runApply (fmap return f) constant = Sys.constant localVariable = Sys.localVariable arg :: (Var var, Monoid w) => var w s a -> Sys.Apply w s a arg = Sys.arg . plainVariable assignment2 :: (Var var, Monoid w) => (a -> b) -> var w s a -> var w s b -> T w s () assignment2 f a = runApply $ liftA f (arg a) assignment3 :: (Var var, Monoid w) => (a -> b -> c) -> var w s a -> var w s b -> var w s c -> T w s () assignment3 f a b = runApply $ liftA2 f (arg a) (arg b) solve :: T () s a -> ST s a solve = fmap fst . MW.runWriterT . Sys.solve query :: (Var var, Monoid w) => var w s a -> ST s (Maybe a) query = Sys.query . plainVariable