unique-logic 0.3 → 0.4
raw patch · 17 files changed
+811/−398 lines, 17 filesdep +explicit-exceptiondep +semigroupsdep ~QuickCheckdep ~non-emptydep ~transformers
Dependencies added: explicit-exception, semigroups
Dependency ranges changed: QuickCheck, non-empty, transformers, utility-ht
Files
- src/UniqueLogic/ST/Duplicate.hs +166/−0
- src/UniqueLogic/ST/Example/Expression.hs +1/−1
- src/UniqueLogic/ST/Example/Label.hs +17/−41
- src/UniqueLogic/ST/Example/Rule.hs +1/−1
- src/UniqueLogic/ST/Example/Term.hs +32/−0
- src/UniqueLogic/ST/Example/Verify.hs +135/−0
- src/UniqueLogic/ST/Expression.hs +28/−27
- src/UniqueLogic/ST/MonadTrans.hs +68/−0
- src/UniqueLogic/ST/Rule.hs +19/−20
- src/UniqueLogic/ST/RuleLog.hs +0/−35
- src/UniqueLogic/ST/System.hs +207/−34
- src/UniqueLogic/ST/System/Label.hs +51/−0
- src/UniqueLogic/ST/System/Simple.hs +43/−0
- src/UniqueLogic/ST/SystemLabel.hs +0/−46
- src/UniqueLogic/ST/SystemLog.hs +0/−167
- src/UniqueLogic/ST/Test.hs +10/−5
- unique-logic.cabal +33/−21
+ src/UniqueLogic/ST/Duplicate.hs view
@@ -0,0 +1,166 @@+{- |+This module provides several ways to cope with over-determined values.+-}+module UniqueLogic.ST.Duplicate (+ C, accept,+ Ignore(Ignore),+ Forbid(Forbid),+ Verify(Verify),+ ) where+++class C a where+ accept :: a -> a -> Bool++instance (C a, C b) => C (a, b) where+ accept (a0,b0) (a1,b1) =+ accept a0 a1 && accept b0 b1++instance (C a, C b, C c) => C (a, b, c) where+ accept (a0,b0,c0) (a1,b1,c1) =+ accept a0 a1 && accept b0 b1 && accept c0 c1+++{- |+Ignore duplicate ways to determine a variable.+The chosen value depends on the particular algorithm.+-}+newtype Ignore a = Ignore a deriving (Eq, Ord, Show)++instance C (Ignore a) where accept _ _ = True++ignore1 :: (a -> b) -> Ignore a -> Ignore b+ignore1 f (Ignore x) = Ignore $ f x++ignore2 :: (a -> b -> c) -> Ignore a -> Ignore b -> Ignore c+ignore2 f (Ignore x) (Ignore y) = Ignore $ f x y++instance Num a => Num (Ignore a) where+ fromInteger = Ignore . fromInteger+ (+) = ignore2 (+)+ (-) = ignore2 (-)+ (*) = ignore2 (*)+ abs = ignore1 abs+ signum = ignore1 signum++instance Fractional a => Fractional (Ignore a) where+ fromRational = Ignore . fromRational+ (/) = ignore2 (/)++instance Floating a => Floating (Ignore a) where+ pi = Ignore pi+ exp = ignore1 exp+ sqrt = ignore1 sqrt+ log = ignore1 log+ (**) = ignore2 (**)+ logBase = ignore2 logBase+ sin = ignore1 sin+ tan = ignore1 tan+ cos = ignore1 cos+ asin = ignore1 asin+ atan = ignore1 atan+ acos = ignore1 acos+ sinh = ignore1 sinh+ tanh = ignore1 tanh+ cosh = ignore1 cosh+ asinh = ignore1 asinh+ atanh = ignore1 atanh+ acosh = ignore1 acosh++++{- |+Duplicate ways to determine a variable value+are always considered an error.+If you use @Rule@s or @Expression@s this is not a good idea,+since every rule is over-determined.+-}+newtype Forbid a = Forbid a deriving (Eq, Ord, Show)++instance C (Forbid a) where accept _ _ = False++forbid1 :: (a -> b) -> Forbid a -> Forbid b+forbid1 f (Forbid x) = Forbid $ f x++forbid2 :: (a -> b -> c) -> Forbid a -> Forbid b -> Forbid c+forbid2 f (Forbid x) (Forbid y) = Forbid $ f x y++instance Num a => Num (Forbid a) where+ fromInteger = Forbid . fromInteger+ (+) = forbid2 (+)+ (-) = forbid2 (-)+ (*) = forbid2 (*)+ abs = forbid1 abs+ signum = forbid1 signum++instance Fractional a => Fractional (Forbid a) where+ fromRational = Forbid . fromRational+ (/) = forbid2 (/)++instance Floating a => Floating (Forbid a) where+ pi = Forbid pi+ exp = forbid1 exp+ sqrt = forbid1 sqrt+ log = forbid1 log+ (**) = forbid2 (**)+ logBase = forbid2 logBase+ sin = forbid1 sin+ tan = forbid1 tan+ cos = forbid1 cos+ asin = forbid1 asin+ atan = forbid1 atan+ acos = forbid1 acos+ sinh = forbid1 sinh+ tanh = forbid1 tanh+ cosh = forbid1 cosh+ asinh = forbid1 asinh+ atanh = forbid1 atanh+ acosh = forbid1 acosh+++{- |+Duplicate ways to determine a variable value are allowed+as long as every way yields the same result.+\"Same\" is meant with respect to the 'Eq' class.+-}+newtype Verify a = Verify a deriving (Eq, Ord, Show)++instance Eq a => C (Verify a) where accept (Verify x) (Verify y) = x==y++verify1 :: (a -> b) -> Verify a -> Verify b+verify1 f (Verify x) = Verify $ f x++verify2 :: (a -> b -> c) -> Verify a -> Verify b -> Verify c+verify2 f (Verify x) (Verify y) = Verify $ f x y++instance Num a => Num (Verify a) where+ fromInteger = Verify . fromInteger+ (+) = verify2 (+)+ (-) = verify2 (-)+ (*) = verify2 (*)+ abs = verify1 abs+ signum = verify1 signum++instance Fractional a => Fractional (Verify a) where+ fromRational = Verify . fromRational+ (/) = verify2 (/)++instance Floating a => Floating (Verify a) where+ pi = Verify pi+ exp = verify1 exp+ sqrt = verify1 sqrt+ log = verify1 log+ (**) = verify2 (**)+ logBase = verify2 logBase+ sin = verify1 sin+ tan = verify1 tan+ cos = verify1 cos+ asin = verify1 asin+ atan = verify1 atan+ acos = verify1 acos+ sinh = verify1 sinh+ tanh = verify1 tanh+ cosh = verify1 cosh+ asinh = verify1 asinh+ atanh = verify1 atanh+ acosh = verify1 acosh
src/UniqueLogic/ST/Example/Expression.hs view
@@ -3,7 +3,7 @@ where import qualified UniqueLogic.ST.Expression as Expr-import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.System.Simple as Sys import UniqueLogic.ST.Expression ((=:=)) import Control.Monad.ST (runST, )
src/UniqueLogic/ST/Example/Label.hs view
@@ -2,9 +2,11 @@ {-# DEPRECATED "This module is intended for documentation purposes. Do not import it!" #-} where +import qualified UniqueLogic.ST.Example.Term as Term import qualified UniqueLogic.ST.Expression as Expr import qualified UniqueLogic.ST.Rule as Rule-import qualified UniqueLogic.ST.SystemLabel as Sys+import qualified UniqueLogic.ST.System.Label as Sys+import qualified UniqueLogic.ST.Duplicate as Duplicate import UniqueLogic.ST.Expression ((=:=)) import qualified Control.Monad.Trans.Writer as MW@@ -18,47 +20,21 @@ -data Assign = Assign Name Term+data Assign = Assign Term.Name Term.T deriving (Show) type Assigns = [Assign] -data Term =- Const Rational- | Var Name- | Max Term Term- | Add Term Term- | Sub Term Term- | Mul Term Term- | Div Term Term- | Abs Term- | Signum Term- deriving (Show)--type Name = String---instance Num Term where- fromInteger n = Const $ fromInteger n- (+) = Add- (-) = Sub- (*) = Mul- abs = Abs- signum = Signum--instance Fractional Term where- fromRational x = Const x- (/) = Div+type Variable s = Sys.Variable Assigns s (Duplicate.Ignore Term.T) -globalVariable ::- Name -> ST s (Sys.Variable Assigns s Term)+globalVariable :: Term.Name -> ST s (Variable s) globalVariable name = Sys.globalVariable $- \x -> writer (Var name, [Assign name x])+ \(Duplicate.Ignore x) ->+ writer (Duplicate.Ignore $ Term.Var name, [Assign name x]) -constant ::- Rational -> Sys.T Assigns s (Sys.Variable Assigns s Term)-constant = Sys.constant . Const+constant :: Rational -> Sys.T Assigns s (Variable s)+constant = Sys.constant . fromRational {- |@@ -70,7 +46,7 @@ > y*z=6 > z=3 -}-rule :: ((Maybe Term, Maybe Term, Maybe Term), Assigns)+rule :: ((Maybe Term.T, Maybe Term.T, Maybe Term.T), Assigns) rule = runST (do x <- globalVariable "x"@@ -85,11 +61,11 @@ Rule.equ z c3 MT.lift $ liftM3 (,,)- (Sys.query x)- (Sys.query y)- (Sys.query z))+ (Sys.queryIgnore x)+ (Sys.queryIgnore y)+ (Sys.queryIgnore z)) -expression :: ((Maybe Term, Maybe Term), Assigns)+expression :: ((Maybe Term.T, Maybe Term.T), Assigns) expression = runST (do xv <- globalVariable "x"@@ -101,5 +77,5 @@ x*3 =:= y/2 5 =:= 2+x MT.lift $ liftM2 (,)- (Sys.query xv)- (Sys.query yv))+ (Sys.queryIgnore xv)+ (Sys.queryIgnore yv))
src/UniqueLogic/ST/Example/Rule.hs view
@@ -3,7 +3,7 @@ where import qualified UniqueLogic.ST.Rule as Rule-import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.System.Simple as Sys import Control.Monad.ST (runST, ) import Control.Monad (liftM4, )
+ src/UniqueLogic/ST/Example/Term.hs view
@@ -0,0 +1,32 @@+{- |+This module is intended for documentation purposes. Do not import it!+-}+module UniqueLogic.ST.Example.Term where+++data T =+ Const Rational+ | Var Name+ | Max T T+ | Add T T+ | Sub T T+ | Mul T T+ | Div T T+ | Abs T+ | Signum T+ deriving (Show)++type Name = String+++instance Num T where+ fromInteger n = Const $ fromInteger n+ (+) = Add+ (-) = Sub+ (*) = Mul+ abs = Abs+ signum = Signum++instance Fractional T where+ fromRational x = Const x+ (/) = Div
+ src/UniqueLogic/ST/Example/Verify.hs view
@@ -0,0 +1,135 @@+module UniqueLogic.ST.Example.Verify+{-# DEPRECATED "This module is intended for documentation purposes. Do not import it!" #-}+ where++import qualified UniqueLogic.ST.Example.Term as Term+import qualified UniqueLogic.ST.Expression as Expr+import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.Duplicate as Duplicate+import qualified UniqueLogic.ST.MonadTrans as UMT+import UniqueLogic.ST.Expression ((=:=))++import qualified Control.Monad.Exception.Synchronous as ME+import qualified Control.Monad.Trans.Writer as MW+import qualified Control.Monad.Trans.Class as MT+import Control.Monad.Trans.Writer (writer, )+import Control.Monad.Trans.Maybe (MaybeT, mapMaybeT, )+import Control.Monad.ST (ST, runST, )+import Control.Monad (liftM, liftM2, ap, )+import Control.Applicative (Applicative, pure, (<*>), )++import qualified Prelude as P+import Prelude hiding (max, log)++++data Assign = Assign Term.Name Term.T+ deriving (Show)++type Assigns = [Assign]++data TrackedNumber a = TrackedNumber Term.T a+ deriving (Show)++tn1 :: (Term.T -> Term.T) -> (a -> b) -> TrackedNumber a -> TrackedNumber b+tn1 f g (TrackedNumber xt xn) = TrackedNumber (f xt) (g xn)++tn2 :: (Term.T -> Term.T -> Term.T) -> (a -> b -> c) -> TrackedNumber a -> TrackedNumber b -> TrackedNumber c+tn2 f g (TrackedNumber xt xn) (TrackedNumber yt yn) =+ TrackedNumber (f xt yt) (g xn yn)++instance Num a => Num (TrackedNumber a) where+ fromInteger n = TrackedNumber (fromInteger n) (fromInteger n)+ (+) = tn2 (+) (+)+ (-) = tn2 (-) (-)+ (*) = tn2 (*) (*)+ abs = tn1 abs abs+ signum = tn1 signum signum++instance Fractional a => Fractional (TrackedNumber a) where+ fromRational n = TrackedNumber (fromRational n) (fromRational n)+ (/) = tn2 (/) (/)++instance Eq a => Duplicate.C (TrackedNumber a) where+ accept (TrackedNumber _ x) (TrackedNumber _ y) = x==y+++instance (Monad m) => Functor (Track m) where+ fmap = liftM++instance (Monad m) => Applicative (Track m) where+ pure = return+ (<*>) = ap++instance (Monad m) => Monad (Track m) where+ return = Track . UMT.point+ x >>= k = Track $ UMT.bind (runTrack x) (runTrack . k)+++instance MT.MonadTrans Track where+ lift = Track . MT.lift . MT.lift++instance UMT.C Track where+ point = return+ bind = (>>=)++instance Sys.C Track where+ doUpdate =+ Sys.updateAndCheck $ \_ _ ->+ UMT.wrap $ Track $ ME.throwT AnonymousException+++newtype+ Track m a =+ Track {runTrack :: ME.ExceptionalT Exception (MW.WriterT Assigns m) a}++data+ Exception =+ Exception Term.Name (TrackedNumber Rational) (TrackedNumber Rational)+ | AnonymousException+ deriving (Show)++type Variable s = Sys.Variable Track s (TrackedNumber Rational)++globalVariable :: Term.Name -> ST s (Variable s)+globalVariable name =+ Sys.globalVariable+ (\al av -> Sys.updateAndCheck (inconsistency name) al av . update name)++inconsistency ::+ Monad m =>+ Term.Name ->+ TrackedNumber Rational ->+ TrackedNumber Rational ->+ UMT.Wrap Track m ()+inconsistency name old new =+ UMT.wrap $ Track $ ME.throwT $ Exception name old new++update ::+ Term.Name ->+ MaybeT (ST s) (TrackedNumber a) ->+ MaybeT (UMT.Wrap Track (ST s)) (TrackedNumber a)+update name act = do+ (TrackedNumber t x) <- mapMaybeT UMT.lift act+ MT.lift $ UMT.wrap $ Track $ MT.lift $+ writer (TrackedNumber (Term.Var name) x, [Assign name t])+++example ::+ (ME.Exceptional Exception+ (Maybe (TrackedNumber Rational),+ Maybe (TrackedNumber Rational)),+ Assigns)+example =+ runST (do+ xv <- globalVariable "x"+ yv <- globalVariable "y"+ MW.runWriterT $ ME.runExceptionalT $ runTrack $ do+ Sys.solve $ do+ let x = Expr.fromVariable xv+ y = Expr.fromVariable yv+ x*3 =:= y/2+ 5 =:= 2+x+ MT.lift $ liftM2 (,)+ (Sys.query xv)+ (Sys.query yv))
src/UniqueLogic/ST/Expression.hs view
@@ -17,12 +17,11 @@ import qualified UniqueLogic.ST.Rule as Rule import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.Duplicate as Duplicate import Control.Monad (ap, ) import Control.Applicative (Applicative, pure, liftA, liftA2, (<*>), ) -import Data.Monoid (Monoid, )- -- import Control.Category ((.)) -- import Data.Maybe (Maybe) @@ -36,32 +35,32 @@ and the variable at the top-level. The value of the expression equals the value of the top variable. -}-newtype T var w s a = Cons (Sys.T w s (var w s a))+newtype T w s a = Cons (Sys.T w s (Sys.Variable w s a)) {- | Make a constant expression of a simple numeric value. -}-constant :: (Sys.Var var, Monoid w) => a -> T var w s a+constant :: (Sys.C w, Duplicate.C a) => a -> T w s a constant = Cons . Sys.constant -fromVariable :: var w s a -> T var w s a+fromVariable :: Sys.Variable w s a -> T w s a fromVariable = Cons . return fromRule1 ::- (Sys.Var var, Monoid w) =>- (var w s a -> Sys.T w s ()) ->- (T var w s a)+ (Sys.C w, Duplicate.C a) =>+ (Sys.Variable w s a -> Sys.T w s ()) ->+ (T w s a) fromRule1 rule = Cons $ do xv <- Sys.localVariable rule xv return xv fromRule2, _fromRule2 ::- (Sys.Var var, Monoid w) =>- (var w s a -> var w s b -> Sys.T w s ()) ->- (T var w s a -> T var w s b)+ (Sys.C w, Duplicate.C b) =>+ (Sys.Variable w s a -> Sys.Variable w s b -> Sys.T w s ()) ->+ (T w s a -> T w s b) fromRule2 rule (Cons x) = Cons $ do xv <- x yv <- Sys.localVariable@@ -69,9 +68,9 @@ return yv fromRule3, _fromRule3 ::- (Sys.Var var, Monoid w) =>- (var w s a -> var w s b -> var w s c -> Sys.T w s ()) ->- (T var w s a -> T var w s b -> T var w s c)+ (Sys.C w, Duplicate.C c) =>+ (Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s c -> Sys.T w s ()) ->+ (T w s a -> T w s b -> T w s c) fromRule3 rule (Cons x) (Cons y) = Cons $ do xv <- x yv <- y@@ -104,13 +103,13 @@ than using auxiliary 'pair' rules! -} arg ::- T var w s a -> Apply w s (var w s a)+ T w s a -> Apply w s (Sys.Variable w s a) arg (Cons x) = Apply x runApply ::- (Sys.Var var, Monoid w) =>- Apply w s (var w s a -> Sys.T w s ()) ->- T var w s a+ (Sys.C w, Duplicate.C a) =>+ Apply w s (Sys.Variable w s a -> Sys.T w s ()) ->+ T w s a runApply (Apply rule) = Cons $ do f <- rule xv <- Sys.localVariable@@ -124,7 +123,7 @@ _fromRule3 rule x y = runApply $ liftA2 rule (arg x) (arg y) -instance (P.Fractional a, Sys.Var var, Monoid w) => P.Num (T var w s a) where+instance (Sys.C w, Duplicate.C a, P.Fractional a) => P.Num (T w s a) where fromInteger = constant . fromInteger (+) = fromRule3 Rule.add (-) = fromRule3 (\z x y -> Rule.add x y z)@@ -132,20 +131,20 @@ abs = fromRule2 (Sys.assignment2 abs) signum = fromRule2 (Sys.assignment2 signum) -instance (P.Fractional a, Sys.Var var, Monoid w) => P.Fractional (T var w s a) where+instance (Sys.C w, Duplicate.C a, P.Fractional a) => P.Fractional (T w s a) where fromRational = constant . fromRational (/) = fromRule3 (\z x y -> Rule.mul x y z) -sqr :: (P.Floating a, Sys.Var var, Monoid w) => T var w s a -> T var w s a+sqr :: (Sys.C w, Duplicate.C a, P.Floating a) => T w s a -> T w s a sqr = fromRule2 Rule.square -sqrt :: (P.Floating a, Sys.Var var, Monoid w) => T var w s a -> T var w s a+sqrt :: (Sys.C w, Duplicate.C a, P.Floating a) => T w s a -> T w s a sqrt = fromRule2 (flip Rule.square) infixl 4 =!= -(=!=) :: (Sys.Var var, Monoid w) => T var w s a -> T var w s a -> T var w s a+(=!=) :: (Sys.C w) => T w s a -> T w s a -> T w s a (=!=) (Cons x) (Cons y) = Cons $ do xv <- x yv <- y@@ -154,7 +153,7 @@ infix 0 =:= -(=:=) :: (Sys.Var var, Monoid w) => T var w s a -> T var w s a -> Sys.T w s ()+(=:=) :: (Sys.C w) => T w s a -> T w s a -> Sys.T w s () (=:=) (Cons x) (Cons y) = do xv <- x yv <- y@@ -166,15 +165,17 @@ including Eq superclass and comparisons, but we need to compute maxima. -}-max :: (Ord a, Sys.Var var, Monoid w) => T var w s a -> T var w s a -> T var w s a+max :: (Sys.C w, Ord a, Duplicate.C a) => T w s a -> T w s a -> T w s a max = fromRule3 Rule.max -maximum :: (Ord a, Sys.Var var, Monoid w) => [T var w s a] -> T var w s a+maximum :: (Sys.C w, Ord a, Duplicate.C a) => [T w s a] -> T w s a maximum = foldl1 max {- | Construct or decompose a pair. -}-pair :: (Sys.Var var, Monoid w) => T var w s a -> T var w s b -> T var w s (a,b)+pair ::+ (Sys.C w, Duplicate.C a, Duplicate.C b) =>+ T w s a -> T w s b -> T w s (a,b) pair = fromRule3 Rule.pair
+ src/UniqueLogic/ST/MonadTrans.hs view
@@ -0,0 +1,68 @@+{-+This module could also be part of 'transformers'.+-}+module UniqueLogic.ST.MonadTrans where++import qualified Control.Monad.Exception.Synchronous as E++import qualified Control.Monad.Trans.Class as MT+import qualified Control.Monad.Trans.Writer as MW+import qualified Control.Monad.Trans.Maybe as MM+import qualified Control.Monad.Trans.Identity as MI++import Control.Applicative (Applicative, pure, (<*>), Const(Const))+import Control.Monad (liftM, ap, )+import Data.Monoid (Monoid, )+++{- |+Provide the methods that make a transformed monad a monad.+-}+class MT.MonadTrans t => C t where+ point :: Monad m => a -> t m a+ bind :: Monad m => t m a -> (a -> t m b) -> t m b++instance C MI.IdentityT where+ point = return+ bind = (>>=)++instance (Monoid w) => C (MW.WriterT w) where+ point = return+ bind = (>>=)++instance C (E.ExceptionalT e) where+ point = return+ bind = (>>=)++instance C MM.MaybeT where+ point = return+ bind = (>>=)+++{- |+Build a regular monad for generic monad transformer and monad.+The 'Const' type allows us to force the kind (m :: * -> *)+without using ExplicitKindSignatures.+-}+newtype Wrap t m a = Wrap (Const (t m a) (m a))++wrap :: t m a -> Wrap t m a+wrap = Wrap . Const++unwrap :: Wrap t m a -> t m a+unwrap (Wrap (Const m)) = m++lift :: (C t, Monad m) => m a -> Wrap t m a+lift = wrap . MT.lift+++instance (C t, Monad m) => Functor (Wrap t m) where+ fmap = liftM++instance (C t, Monad m) => Applicative (Wrap t m) where+ pure = return+ (<*>) = ap++instance (C t, Monad m) => Monad (Wrap t m) where+ return = wrap . point+ x >>= k = wrap $ bind (unwrap x) (unwrap . k)
src/UniqueLogic/ST/Rule.hs view
@@ -7,17 +7,16 @@ ) where import qualified UniqueLogic.ST.System as Sys--import Data.Monoid (Monoid, )+import qualified UniqueLogic.ST.MonadTrans as UMT import qualified Prelude as P import Prelude hiding (max) generic2 ::- (Sys.Var var, Monoid w) =>+ (UMT.C w) => (b -> a) -> (a -> b) ->- var w s a -> var w s b -> Sys.T w s ()+ Sys.Variable w s a -> Sys.Variable w s b -> Sys.T w s () generic2 f g x y = sequence_ $ Sys.assignment2 f y x :@@ -25,9 +24,9 @@ [] generic3 ::- (Sys.Var var, Monoid w) =>+ (UMT.C w) => (b -> c -> a) -> (c -> a -> b) -> (a -> b -> c) ->- var w s a -> var w s b -> var w s c -> Sys.T w s ()+ Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s c -> Sys.T w s () generic3 f g h x y z = sequence_ $ Sys.assignment3 f y z x :@@ -37,13 +36,13 @@ equ ::- (Sys.Var var, Monoid w) =>- var w s a -> var w s a -> Sys.T w s ()+ (UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () equ = generic2 id id max ::- (Ord a, Sys.Var var, Monoid w) =>- var w s a -> var w s a -> var w s a -> Sys.T w s ()+ (Ord a, UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () max = Sys.assignment3 P.max @@ -57,25 +56,25 @@ This is the way, 'generic2' and 'generic3' work. -} pair ::- (Sys.Var var, Monoid w) =>- var w s a -> var w s b -> var w s (a,b) -> Sys.T w s ()+ (UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s (a,b) -> Sys.T w s () pair x y xy = Sys.assignment3 (,) x y xy >> Sys.assignment2 fst xy x >> Sys.assignment2 snd xy y -add :: (Num a, Sys.Var var, Monoid w) =>- var w s a -> var w s a -> var w s a -> Sys.T w s ()+add :: (Num a, UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () add = generic3 subtract (-) (+) -mul :: (Fractional a, Sys.Var var, Monoid w) =>- var w s a -> var w s a -> var w s a -> Sys.T w s ()+mul :: (Fractional a, UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () mul = generic3 (flip (/)) (/) (*) -square :: (Floating a, Sys.Var var, Monoid w) =>- var w s a -> var w s a -> Sys.T w s ()+square :: (Floating a, UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () square = generic2 sqrt (^(2::Int)) -pow :: (Floating a, Sys.Var var, Monoid w) =>- var w s a -> var w s a -> var w s a -> Sys.T w s ()+pow :: (Floating a, UMT.C w) =>+ Sys.Variable w s a -> Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s () pow = generic3 (\x y -> y ** recip x) (flip logBase) (**)
− src/UniqueLogic/ST/RuleLog.hs
@@ -1,35 +0,0 @@-module UniqueLogic.ST.RuleLog (- -- * Custom rules- generic2,- generic3,- ) where--import qualified UniqueLogic.ST.SystemLog as Sys--import Control.Monad.Trans.Writer (Writer, )-import Data.Monoid (Monoid, )--import qualified Prelude as P-import Prelude hiding (max)---generic2 ::- Monoid w =>- (b -> Writer w a) -> (a -> Writer w b) ->- Sys.Variable w s a -> Sys.Variable w s b -> Sys.T w s ()-generic2 f g x y =- sequence_ $- Sys.assignment2 f y x :- Sys.assignment2 g x y :- []--generic3 ::- Monoid w =>- (b -> c -> Writer w a) -> (c -> a -> Writer w b) -> (a -> b -> Writer w c) ->- Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s c -> Sys.T w s ()-generic3 f g h x y z =- sequence_ $- Sys.assignment3 f y z x :- Sys.assignment3 g z x y :- Sys.assignment3 h x y z :- []
src/UniqueLogic/ST/System.hs view
@@ -1,69 +1,242 @@ module UniqueLogic.ST.System ( -- * Preparation- Var, Variable,- Sys.globalVariable,- plainVariable,+ globalVariable,+ -- * Handle duplicates+ C, doUpdate,+ simpleUpdate, -- should be private in future+ updateIfNew, -- should be private or with special type+ updateAndCheck,+ Fragile(break), -- * Posing statements T, localVariable, constant, assignment2, assignment3,- Sys.Apply, arg, runApply,+ Apply, arg, runApply, -- * Solution solve, query,+ queryForbid,+ queryIgnore,+ queryVerify, ) where -import qualified UniqueLogic.ST.SystemLog as Sys-import UniqueLogic.ST.SystemLog (T, Variable)-+import qualified Control.Monad.Exception.Synchronous as E import qualified Control.Monad.Trans.Writer as MW-import Control.Applicative (liftA, liftA2, )+import qualified Control.Monad.Trans.Class as MT+import qualified UniqueLogic.ST.MonadTrans as UMT+import qualified UniqueLogic.ST.Duplicate as Duplicate+import qualified Data.Foldable as Fold+import Control.Monad.Trans.Writer (WriterT, )+import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT, mapMaybeT, )+import Control.Monad.Trans.Identity (IdentityT, ) import Control.Monad.ST (ST, )+import Control.Monad.HT (void, (<=<), )+import Control.Monad (when, liftM2, ap, )+import Control.Applicative (Applicative, pure, (<*>), )+import Data.Functor.Compose (Compose(Compose)) +import Data.STRef (STRef, newSTRef, modifySTRef, readSTRef, writeSTRef, )+import Data.Maybe (isNothing, ) import Data.Monoid (Monoid, ) +import Prelude hiding (break) -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+data Variable w s a =+ Variable {+ varUpdate :: MaybeT (ST s) a -> Update w s,+ dependsRef :: STRef s [Update w s],+ valueRef :: STRef s (Maybe a)+ } -arg :: (Var var, Monoid w) => var w s a -> Sys.Apply w s a-arg = Sys.arg . plainVariable+type Update w s = UMT.Wrap w (ST s) () +type Updater w s a =+ STRef s [Update w s] -> STRef s (Maybe a) ->+ MaybeT (UMT.Wrap w (ST s)) a -> Update w s +type SimpleUpdater w s a =+ STRef s [Update w s] -> STRef s (Maybe a) ->+ MaybeT (ST s) a -> Update w s++newtype T w s a =+ Cons {run :: WriterT [STRef s [Update w s]] (ST s) a}++instance Functor (T w s) where+ fmap f (Cons x) = Cons (fmap f x)++instance Applicative (T w s) where+ pure = Cons . return+ (<*>) = ap++instance Monad (T w s) where+ return = Cons . return+ Cons x >>= k = Cons $ run . k =<< x+++lift :: ST s a -> T w s a+lift = Cons . MT.lift++globalVariable ::+ (UMT.C w, Duplicate.C a) =>+ SimpleUpdater w s a -> ST s (Variable w s a)+globalVariable update = object update Nothing++localVariable :: (C w, Duplicate.C a) => T w s (Variable w s a)+localVariable = lift $ globalVariable simpleUpdate++constant ::+ (C w, Duplicate.C a) =>+ a -> T w s (Variable w s a)+constant a =+ do v <- lift $ object simpleUpdate $ Just a+ Cons $ MW.tell [dependsRef v]+ return v++object ::+ (STRef s [Update w s] -> STRef s (Maybe a) ->+ MaybeT (ST s) a -> Update w s) ->+ Maybe a -> ST s (Variable w s a)+object updater ma = do+ al <- newSTRef []+ av <- newSTRef ma+ return $ Variable (updater al av) al av++resolve ::+ UMT.C w =>+ STRef s [Update w s] -> Update w s+resolve =+ sequence_ <=< UMT.lift . readSTRef++solve ::+ UMT.C w =>+ T w s a -> w (ST s) a+solve (Cons m) = UMT.unwrap $ do+ (a,w) <- UMT.lift $ MW.runWriterT m+ mapM_ resolve w+ return a++query :: Variable w s a -> ST s (Maybe a)+query = readSTRef . valueRef++queryForbid :: Variable w s (Duplicate.Forbid a) -> ST s (Maybe a)+queryForbid = fmap (fmap (\(Duplicate.Forbid a) -> a)) . query++queryIgnore :: Variable w s (Duplicate.Ignore a) -> ST s (Maybe a)+queryIgnore = fmap (fmap (\(Duplicate.Ignore a) -> a)) . query++queryVerify :: Variable w s (Duplicate.Verify a) -> ST s (Maybe a)+queryVerify = fmap (fmap (\(Duplicate.Verify a) -> a)) . query+++updateIfNew :: (C w, Duplicate.C a) => Updater w s a+updateIfNew al av act = do+ as <- UMT.lift $ readSTRef av+ when (isNothing as) $ void $ runMaybeT $ do+ MT.lift . UMT.lift . writeSTRef av . Just =<< act+ MT.lift $ resolve al+++class Inconsistency e where+ inconsistency :: e++instance+ Inconsistency e =>+ Fragile (E.ExceptionalT e) where+ break =+ UMT.wrap $ E.throwT inconsistency++class C t => Fragile t where+ break :: Monad m => UMT.Wrap t m a++updateAndCheck ::+ (UMT.C w, Duplicate.C a) =>+ (a -> a -> UMT.Wrap w (ST s) ()) ->+ Updater w s a+updateAndCheck customBreak al av act = do+ maold <- UMT.lift $ readSTRef av+ manew <- runMaybeT act+ Fold.forM_ manew $ \anew -> do+ UMT.lift . writeSTRef av . Just $ anew+ case maold of+ Just aold ->+ when (not $ Duplicate.accept aold anew) $+ customBreak aold anew+ Nothing -> resolve al+++class UMT.C w => C w where+ doUpdate :: (Duplicate.C a) => Updater w s a++instance C IdentityT where+ doUpdate = updateIfNew++instance (Monoid w) => C (MW.WriterT w) where+ doUpdate = updateIfNew++instance (Inconsistency e) => C (E.ExceptionalT e) where+ doUpdate = updateAndCheck $ \_ _ -> break++simpleUpdate :: (C w, Duplicate.C a) => SimpleUpdater w s a+simpleUpdate al av = doUpdate al av . mapMaybeT UMT.lift+++readSTRefM :: STRef s (Maybe a) -> MaybeT (ST s) a+readSTRefM = MaybeT . readSTRef++ assignment2 ::- (Var var, Monoid w) =>+ UMT.C w => (a -> b) ->- var w s a -> var w s b ->+ Variable w s a -> Variable w s b -> T w s ()-assignment2 f a =- runApply $ liftA f (arg a)+assignment2 f (Variable _ al av) b =+ let update =+ varUpdate b $ fmap f $ readSTRefM av+ in lift $+ modifySTRef al (update :) assignment3 ::- (Var var, Monoid w) =>+ UMT.C w => (a -> b -> c) ->- var w s a -> var w s b -> var w s c ->+ Variable w s a -> Variable w s b -> Variable w s c -> T w s ()-assignment3 f a b =- runApply $ liftA2 f (arg a) (arg b)+assignment3 f (Variable _ al av) (Variable _ bl bv) c =+ let update =+ varUpdate c $+ liftM2 f (readSTRefM av) (readSTRefM bv)+ in lift $+ modifySTRef al (update :) >>+ modifySTRef bl (update :) -solve :: T () s a -> ST s a-solve = fmap fst . MW.runWriterT . Sys.solve+newtype Apply w s a =+ Apply (Compose (MW.Writer [STRef s [Update w s]]) (MaybeT (ST s)) a) -query :: (Var var, Monoid w) => var w s a -> ST s (Maybe a)-query = Sys.query . plainVariable+{- |+This function allows to generalize 'assignment2' and 'assignment3' to more arguments.+You could achieve the same with nested applications of @assignment3 (,)@.+-}+arg :: Variable w s a -> Apply w s a+arg (Variable _update al av) =+ Apply $ Compose $ MW.writer (MaybeT $ readSTRef av, [al])++instance Functor (Apply w s) where+ fmap f (Apply a) = Apply $ fmap f a++instance Applicative (Apply w s) where+ pure a = Apply $ pure a+ Apply f <*> Apply a = Apply $ f <*> a+++runApply ::+ UMT.C w =>+ Apply w s a -> Variable w s a -> T w s ()+runApply (Apply (Compose w)) a =+ case MW.runWriter w of+ (f, refs) ->+ lift $ Fold.forM_ refs $ flip modifySTRef (varUpdate a f :)
+ src/UniqueLogic/ST/System/Label.hs view
@@ -0,0 +1,51 @@+module UniqueLogic.ST.System.Label (+ -- * Preparation+ Variable,+ globalVariable,+ -- * Posing statements+ T,+ Sys.localVariable,+ Sys.constant,+ Sys.assignment2,+ Sys.assignment3,+ Sys.Apply, Sys.arg, Sys.runApply,+ -- * Solution+ Sys.solve,+ Sys.query,+ Sys.queryForbid,+ Sys.queryIgnore,+ Sys.queryVerify,+ ) where++import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.MonadTrans as UMT+import qualified UniqueLogic.ST.Duplicate as Duplicate++import qualified Control.Monad.Trans.Writer as MW+import Control.Monad.Trans.Maybe (MaybeT, mapMaybeT, )+import Control.Monad.ST (ST, )++import Data.Monoid (Monoid, )+import Data.Traversable (traverse, )++import Prelude hiding (log, )+++type T w = Sys.T (MW.WriterT w)+type Variable w = Sys.Variable (MW.WriterT w)++globalVariable ::+ (Monoid w, Duplicate.C a) =>+ (a -> MW.Writer w a) -> ST s (Variable w s a)+globalVariable log =+ Sys.globalVariable+ (\al av -> Sys.updateIfNew al av . wrap log)++wrap ::+ (Monoid w) =>+ (a -> MW.Writer w b) ->+ MaybeT (ST s) a -> MaybeT (UMT.Wrap (MW.WriterT w) (ST s)) b+wrap log =+ mapMaybeT $+ UMT.wrap . MW.WriterT . fmap (MW.runWriter . traverse log)+-- UMT.wrap . MW.writer . MW.runWriter . traverse log <=< UMT.lift
+ src/UniqueLogic/ST/System/Simple.hs view
@@ -0,0 +1,43 @@+module UniqueLogic.ST.System.Simple (+ -- * Preparation+ Variable,+ globalVariable,+ -- * Posing statements+ T,+ localVariable,+ constant,+ Sys.assignment2,+ Sys.assignment3,+ Sys.Apply, Sys.arg, Sys.runApply,+ -- * Solution+ solve,+ query,+ ) where++import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.Duplicate as Duplicate++import Control.Monad.Trans.Identity (IdentityT, runIdentityT, )+import Control.Monad.ST (ST, )+++type T = Sys.T IdentityT++type Variable s a = Sys.Variable IdentityT s (Duplicate.Ignore a)+++globalVariable :: ST s (Variable s a)+globalVariable =+ Sys.globalVariable Sys.simpleUpdate++localVariable :: T s (Variable s a)+localVariable = Sys.localVariable++constant :: a -> T s (Variable s a)+constant = Sys.constant . Duplicate.Ignore++solve :: T s a -> ST s a+solve = runIdentityT . Sys.solve++query :: Variable s a -> ST s (Maybe a)+query = fmap (fmap (\(Duplicate.Ignore a) -> a)) . Sys.query
− src/UniqueLogic/ST/SystemLabel.hs
@@ -1,46 +0,0 @@-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
− src/UniqueLogic/ST/SystemLog.hs
@@ -1,167 +0,0 @@-module UniqueLogic.ST.SystemLog (- -- * Preparation- Variable,- globalVariable,- -- * Posing statements- T,- localVariable,- constant,- assignment2,- assignment3,- Apply, arg, runApply,- -- * Solution- solve,- query,- ) where--import qualified Control.Monad.Trans.Writer as MW-import qualified Control.Monad.Trans.Class as MT-import qualified Data.Foldable as Fold-import Control.Monad.Trans.Writer (WriterT, Writer, )-import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT, mapMaybeT, )-import Control.Monad.ST (ST, )-import Control.Monad.HT ((<=<), )-import Control.Monad (when, liftM2, ap, void, )-import Control.Applicative (Applicative, pure, (<*>), )-import Data.Functor.Compose (Compose(Compose))--import Data.STRef (STRef, newSTRef, modifySTRef, readSTRef, writeSTRef, )-import Data.Monoid (Monoid, )-import Data.Maybe (isNothing, )---data Variable w s a =- Variable {- dependsRef :: STRef s [Update w s],- valueRef :: STRef s (Maybe a)- }--type Update w s = WriterT w (ST s) ()--newtype T w s a =- Cons {run :: WriterT [STRef s [Update w s]] (ST s) a}--instance Functor (T w s) where- fmap f (Cons x) = Cons (fmap f x)--instance Applicative (T w s) where- pure = Cons . return- (<*>) = ap--instance Monad (T w s) where- return = Cons . return- Cons x >>= k = Cons $ run . k =<< x---lift :: ST s a -> T w s a-lift = Cons . MT.lift--localVariable :: T w s (Variable w s a)-localVariable = lift globalVariable--globalVariable :: ST s (Variable w s a)-globalVariable = object Nothing--constant :: a -> T w s (Variable w s a)-constant a =- do v <- lift $ object $ Just a- Cons $ MW.tell [dependsRef v]- return v--object :: Maybe a -> ST s (Variable w s a)-object ma =- liftM2 Variable (newSTRef []) (newSTRef ma)--resolve ::- Monoid w =>- STRef s [Update w s] -> Update w s-resolve =- sequence_ <=< MT.lift . readSTRef--solve ::- Monoid w =>- T w s a -> WriterT w (ST s) a-solve (Cons m) = do- (a,w) <- MT.lift $ MW.runWriterT m- mapM_ resolve w- return a--query :: Variable w s a -> ST s (Maybe a)-query = readSTRef . valueRef---mw ::- (Monoid w, Monad st) =>- MaybeT st (Writer w a) -> MaybeT (WriterT w st) a--- st (Maybe (Writer w a)) -> WriterT w st (Maybe a)-mw act = do- mwa <- mapMaybeT MT.lift act- case MW.runWriter mwa of- (a,w) -> MT.lift $ MW.tell w >> return a--updateIfNew ::- Monoid w =>- Variable w s a -> MaybeT (ST s) (Writer w a) -> Update w s-updateIfNew (Variable al av) act = do- as <- MT.lift $ readSTRef av- when (isNothing as) $ void $ runMaybeT $ do- MT.lift . MT.lift . writeSTRef av . Just =<< mw act- MT.lift $ resolve al--readSTRefM :: STRef s (Maybe a) -> MaybeT (ST s) a-readSTRefM = MaybeT . readSTRef---assignment2 ::- Monoid w =>- (a -> Writer w b) ->- Variable w s a -> Variable w s b ->- T w s ()-assignment2 f (Variable al av) b =- let update =- updateIfNew b $ fmap f $ readSTRefM av- in lift $- modifySTRef al (update :)--assignment3 ::- Monoid w =>- (a -> b -> Writer w c) ->- Variable w s a -> Variable w s b -> Variable w s c ->- T w s ()-assignment3 f (Variable al av) (Variable bl bv) c =- let update =- updateIfNew c $- liftM2 f (readSTRefM av) (readSTRefM bv)- in lift $- modifySTRef al (update :) >>- modifySTRef bl (update :)---data Apply w s a =- Apply (Compose (MW.Writer [STRef s [Update w s]]) (MaybeT (ST s)) a)---{- |-This function allows to generalize 'assignment2' and 'assignment3' to more arguments.-You could achieve the same with nested applications of @assignment3 (,)@.--}-arg :: Monoid w => Variable w s a -> Apply w s a-arg (Variable al av) =- Apply $ Compose $ MW.writer (readSTRefM av, [al])---instance Monoid w => Functor (Apply w s) where- fmap f (Apply a) = Apply $ fmap f a--instance Monoid w => Applicative (Apply w s) where- pure a = Apply $ pure a- Apply f <*> Apply a = Apply $ f <*> a---runApply ::- Monoid w =>- Apply w s (Writer w a) -> Variable w s a -> T w s ()-runApply (Apply (Compose w)) a =- case MW.runWriter w of- (f, refs) ->- lift $ Fold.forM_ refs $ flip modifySTRef (updateIfNew a f :)
src/UniqueLogic/ST/Test.hs view
@@ -1,14 +1,17 @@ module Main where import qualified UniqueLogic.ST.Expression as Expr-import qualified UniqueLogic.ST.System as Sys+import qualified UniqueLogic.ST.System.Simple as Sys+import qualified UniqueLogic.ST.Duplicate as Duplicate import UniqueLogic.ST.Expression ((=:=)) import qualified Control.Monad.Trans.Class as MT import qualified Control.Monad.Trans.Writer as MW+import Control.Monad.Trans.Identity (IdentityT, ) import Control.Monad.ST (ST, runST, ) import Control.Monad (join, liftM2, ) import Data.Monoid (Monoid(mempty, mappend))+import Data.Semigroup (Semigroup((<>)), ) import Data.List (sortBy, ) import Data.Ord.HT (comparing, )@@ -24,9 +27,12 @@ newtype Check s = Check {runCheck :: ST s Bool} +instance Semigroup (Check s) where+ Check x <> Check y = Check $ liftM2 (&&) x y+ instance Monoid (Check s) where mempty = Check $ return True- mappend (Check x) (Check y) = Check $ liftM2 (&&) x y+ mappend = (<>) {- Take a system of six equations and seven variables@@ -40,10 +46,9 @@ runST (join . fmap runCheck . Sys.solve $ MW.execWriterT $ do let variable ::- (Monoid w) => Int -> Rational ->- MW.WriterT (Check s) (Sys.T w s)- (Expr.T Sys.Variable w s Rational)+ MW.WriterT (Check s) (Sys.T s)+ (Expr.T IdentityT s (Duplicate.Ignore Rational)) variable n x = do v <- MT.lift $
unique-logic.cabal view
@@ -1,10 +1,10 @@ Name: unique-logic-Version: 0.3+Version: 0.4 License: BSD3 License-File: LICENSE Author: Henning Thielemann Maintainer: Henning Thielemann <haskell@henning-thielemann.de>-Homepage: http://code.haskell.org/~thielema/unique-logic/+Homepage: http://hub.darcs.net/thielema/unique-logic/ Category: Logic programming Synopsis: Solve simple simultaneous equations Description:@@ -16,8 +16,10 @@ Only one solution is computed. Simultaneous equations with multiple solutions are not allowed. However, variables may remain undefined.- We do not even check for consistency,- since with floating point numbers even simple rules may not be consistent.+ The solver may optionally check for consistency.+ It does not do so by default+ since with floating point numbers or symbolic expressions+ even simple rules may not be consistent. . The modules ordered with respect to abstraction level are: .@@ -38,8 +40,12 @@ Example: @(a+b)*c =:= d@ resolves to @a+b = x, x*c = d@. For an executable example see "UniqueLogic.ST.Example.Expression". .- * "UniqueLogic.ST.SystemLabel":- Provides a new type for named variables.+ * "UniqueLogic.ST.System.Simple":+ Provides specialised functions from "UniqueLogic.ST.System"+ for the case of a system without labels and consistency checks.+ .+ * "UniqueLogic.ST.System.Label":+ Provides a custom constructor for variables. When creating a variable you decide whether and how an assignment to this variable shall be logged. There is an example that shows how to solve a logic system@@ -47,52 +53,58 @@ The naming and logging allows us to observe shared intermediate results. For an executable example see "UniqueLogic.ST.Example.Label". .- * "UniqueLogic.ST.SystemLog", "UniqueLogic.ST.RuleLog":- These modules allow to log an assignment- depending on the arguments to an assignment.- This is more general than "UniqueLogic.ST.SystemLabel"- which allows only dependencies on the result of an assignment.+ * By using more sophisticated monad transformers,+ we can check the equations for consistency,+ report inconsistencies and how they arised.+ We demonstrate that in "UniqueLogic.ST.Example.Verify".+ .+ The package is purely Haskell 98. Tested-With: GHC==7.4.2 Cabal-Version: >=1.8 Build-Type: Simple Source-Repository this- Tag: 0.3+ Tag: 0.4 Type: darcs- Location: http://code.haskell.org/~thielema/unique-logic/+ Location: http://hub.darcs.net/thielema/unique-logic/ Source-Repository head Type: darcs- Location: http://code.haskell.org/~thielema/unique-logic/+ Location: http://hub.darcs.net/thielema/unique-logic/ Library Build-Depends:- transformers >=0.2 && <0.4,- utility-ht >=0.0.1 && <0.1,+ explicit-exception >=0.1.7 && <0.2,+ transformers >=0.2 && <0.6,+ utility-ht >=0.0.9 && <0.1, base >= 4 && <5 GHC-Options: -Wall Hs-Source-Dirs: src Exposed-Modules:+ UniqueLogic.ST.MonadTrans+ UniqueLogic.ST.Duplicate UniqueLogic.ST.System- UniqueLogic.ST.SystemLog- UniqueLogic.ST.SystemLabel+ UniqueLogic.ST.System.Simple+ UniqueLogic.ST.System.Label UniqueLogic.ST.Rule- UniqueLogic.ST.RuleLog UniqueLogic.ST.Expression -- example modules UniqueLogic.ST.Example.Rule UniqueLogic.ST.Example.Label UniqueLogic.ST.Example.Expression+ UniqueLogic.ST.Example.Verify+ UniqueLogic.ST.Example.Term Test-Suite test-unique-logic Type: exitcode-stdio-1.0 Main-Is: src/UniqueLogic/ST/Test.hs GHC-Options: -Wall Build-Depends:- QuickCheck >=2.4 && <2.6,+ QuickCheck >=2.4 && <3, unique-logic,- non-empty >=0.0 && <0.1,+ non-empty >=0.0 && <0.4,+ semigroups >=0.1 && <1.0, transformers, utility-ht, base