module UniqueLogic.ST.Rule (
   -- * Custom rules
   generic2,
   generic3,
   -- * Common rules
   equ, pair, max, add, mul, square, pow,
   ) where

import qualified UniqueLogic.ST.System as Sys
import qualified UniqueLogic.ST.MonadTrans as UMT

import qualified Prelude as P
import Prelude hiding (max)


generic2 ::
   (UMT.C w) =>
   (b -> a) -> (a -> b) ->
   Sys.Variable w s a -> Sys.Variable w s b -> Sys.T w s ()
generic2 :: forall (w :: (* -> *) -> * -> *) b a s.
C w =>
(b -> a)
-> (a -> b) -> Variable w s a -> Variable w s b -> T w s ()
generic2 b -> a
f a -> b
g Variable w s a
x Variable w s b
y =
   forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ forall a b. (a -> b) -> a -> b
$
   forall (w :: (* -> *) -> * -> *) a b s.
C w =>
(a -> b) -> Variable w s a -> Variable w s b -> T w s ()
Sys.assignment2 b -> a
f Variable w s b
y Variable w s a
x forall a. a -> [a] -> [a]
:
   forall (w :: (* -> *) -> * -> *) a b s.
C w =>
(a -> b) -> Variable w s a -> Variable w s b -> T w s ()
Sys.assignment2 a -> b
g Variable w s a
x Variable w s b
y forall a. a -> [a] -> [a]
:
   []

generic3 ::
   (UMT.C w) =>
   (b -> c -> a) -> (c -> a -> b) -> (a -> b -> c) ->
   Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s c -> Sys.T w s ()
generic3 :: forall (w :: (* -> *) -> * -> *) b c a s.
C w =>
(b -> c -> a)
-> (c -> a -> b)
-> (a -> b -> c)
-> Variable w s a
-> Variable w s b
-> Variable w s c
-> T w s ()
generic3 b -> c -> a
f c -> a -> b
g a -> b -> c
h Variable w s a
x Variable w s b
y Variable w s c
z =
   forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ forall a b. (a -> b) -> a -> b
$
   forall (w :: (* -> *) -> * -> *) a b c s.
C w =>
(a -> b -> c)
-> Variable w s a -> Variable w s b -> Variable w s c -> T w s ()
Sys.assignment3 b -> c -> a
f Variable w s b
y Variable w s c
z Variable w s a
x forall a. a -> [a] -> [a]
:
   forall (w :: (* -> *) -> * -> *) a b c s.
C w =>
(a -> b -> c)
-> Variable w s a -> Variable w s b -> Variable w s c -> T w s ()
Sys.assignment3 c -> a -> b
g Variable w s c
z Variable w s a
x Variable w s b
y forall a. a -> [a] -> [a]
:
   forall (w :: (* -> *) -> * -> *) a b c s.
C w =>
(a -> b -> c)
-> Variable w s a -> Variable w s b -> Variable w s c -> T w s ()
Sys.assignment3 a -> b -> c
h Variable w s a
x Variable w s b
y Variable w s c
z forall a. a -> [a] -> [a]
:
   []


equ ::
   (UMT.C w) =>
   Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s ()
equ :: forall (w :: (* -> *) -> * -> *) s a.
C w =>
Variable w s a -> Variable w s a -> T w s ()
equ = forall (w :: (* -> *) -> * -> *) b a s.
C w =>
(b -> a)
-> (a -> b) -> Variable w s a -> Variable w s b -> T w s ()
generic2 forall a. a -> a
id forall a. a -> a
id

max ::
   (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 :: forall a (w :: (* -> *) -> * -> *) s.
(Ord a, C w) =>
Variable w s a -> Variable w s a -> Variable w s a -> T w s ()
max =
   forall (w :: (* -> *) -> * -> *) a b c s.
C w =>
(a -> b -> c)
-> Variable w s a -> Variable w s b -> Variable w s c -> T w s ()
Sys.assignment3 forall a. Ord a => a -> a -> a
P.max

{- |
You might be tempted to use the 'pair' rule to collect parameters
for rules with more than three arguments.
This is generally not a good idea since this way you lose granularity.
For building rules with more than three arguments,
please build according assignments with 'Sys.arg' and 'Sys.runApply'
and bundle these assignments to rules.
This is the way, 'generic2' and 'generic3' work.
-}
pair ::
   (UMT.C w) =>
   Sys.Variable w s a -> Sys.Variable w s b -> Sys.Variable w s (a,b) -> Sys.T w s ()
pair :: forall (w :: (* -> *) -> * -> *) s a b.
C w =>
Variable w s a -> Variable w s b -> Variable w s (a, b) -> T w s ()
pair Variable w s a
x Variable w s b
y Variable w s (a, b)
xy =
   forall (w :: (* -> *) -> * -> *) a b c s.
C w =>
(a -> b -> c)
-> Variable w s a -> Variable w s b -> Variable w s c -> T w s ()
Sys.assignment3 (,) Variable w s a
x Variable w s b
y Variable w s (a, b)
xy forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   forall (w :: (* -> *) -> * -> *) a b s.
C w =>
(a -> b) -> Variable w s a -> Variable w s b -> T w s ()
Sys.assignment2 forall a b. (a, b) -> a
fst Variable w s (a, b)
xy Variable w s a
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   forall (w :: (* -> *) -> * -> *) a b s.
C w =>
(a -> b) -> Variable w s a -> Variable w s b -> T w s ()
Sys.assignment2 forall a b. (a, b) -> b
snd Variable w s (a, b)
xy Variable w s b
y

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 :: forall a (w :: (* -> *) -> * -> *) s.
(Num a, C w) =>
Variable w s a -> Variable w s a -> Variable w s a -> T w s ()
add = forall (w :: (* -> *) -> * -> *) b c a s.
C w =>
(b -> c -> a)
-> (c -> a -> b)
-> (a -> b -> c)
-> Variable w s a
-> Variable w s b
-> Variable w s c
-> T w s ()
generic3 forall a. Num a => a -> a -> a
subtract (-) forall a. Num a => a -> a -> a
(+)

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 :: forall a (w :: (* -> *) -> * -> *) s.
(Fractional a, C w) =>
Variable w s a -> Variable w s a -> Variable w s a -> T w s ()
mul = forall (w :: (* -> *) -> * -> *) b c a s.
C w =>
(b -> c -> a)
-> (c -> a -> b)
-> (a -> b -> c)
-> Variable w s a
-> Variable w s b
-> Variable w s c
-> T w s ()
generic3 (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Fractional a => a -> a -> a
(/)) forall a. Fractional a => a -> a -> a
(/) forall a. Num a => a -> a -> a
(*)

square :: (Floating a, UMT.C w) =>
   Sys.Variable w s a -> Sys.Variable w s a -> Sys.T w s ()
square :: forall a (w :: (* -> *) -> * -> *) s.
(Floating a, C w) =>
Variable w s a -> Variable w s a -> T w s ()
square = forall (w :: (* -> *) -> * -> *) b a s.
C w =>
(b -> a)
-> (a -> b) -> Variable w s a -> Variable w s b -> T w s ()
generic2 forall a. Floating a => a -> a
sqrt (forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2::Int))

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 :: forall a (w :: (* -> *) -> * -> *) s.
(Floating a, C w) =>
Variable w s a -> Variable w s a -> Variable w s a -> T w s ()
pow = forall (w :: (* -> *) -> * -> *) b c a s.
C w =>
(b -> c -> a)
-> (c -> a -> b)
-> (a -> b -> c)
-> Variable w s a
-> Variable w s b
-> Variable w s c
-> T w s ()
generic3 (\a
x a
y -> a
y forall a. Floating a => a -> a -> a
** forall a. Fractional a => a -> a
recip a
x) (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Floating a => a -> a -> a
logBase) forall a. Floating a => a -> a -> a
(**)