{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
module Data.Propagator.Purify
( Purify
, get
, mk, def1, def2, defList
)
where
import System.IO.Unsafe
import Data.Propagator.Class
import System.IO.RecThunk
data Purify p = Purify
{ forall p. Purify p -> p
prop :: p
, forall p. Purify p -> Thunk
pre :: Thunk
, forall p. Purify p -> Thunk
post :: Thunk
}
mk :: Propagator p a => a -> Purify p
mk :: forall p a. Propagator p a => a -> Purify p
mk a
x = IO (Purify p) -> Purify p
forall a. IO a -> a
unsafePerformIO (IO (Purify p) -> Purify p) -> IO (Purify p) -> Purify p
forall a b. (a -> b) -> a -> b
$ do
p
p <- a -> IO p
forall p x. Propagator p x => x -> IO p
newConstProp a
x
Thunk
t1 <- IO Thunk
doneThunk
Thunk
t2 <- IO Thunk
doneThunk
Purify p -> IO (Purify p)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (p -> Thunk -> Thunk -> Purify p
forall p. p -> Thunk -> Thunk -> Purify p
Purify p
p Thunk
t1 Thunk
t2)
new :: Propagator p a => [Thunk] -> [Thunk] -> (p -> IO ()) -> Purify p
new :: forall p a.
Propagator p a =>
[Thunk] -> [Thunk] -> (p -> IO ()) -> Purify p
new [Thunk]
ts1 [Thunk]
ts2 p -> IO ()
act = IO (Purify p) -> Purify p
forall a. IO a -> a
unsafePerformIO (IO (Purify p) -> Purify p) -> IO (Purify p) -> Purify p
forall a b. (a -> b) -> a -> b
$ do
p
p <- IO p
forall p x. Propagator p x => IO p
newProp
Thunk
t1 <- IO [Thunk] -> IO Thunk
thunk (IO [Thunk] -> IO Thunk) -> IO [Thunk] -> IO Thunk
forall a b. (a -> b) -> a -> b
$ p -> IO ()
act p
p IO () -> IO [Thunk] -> IO [Thunk]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Thunk] -> IO [Thunk]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Thunk]
ts1
Thunk
t2 <- IO [Thunk] -> IO Thunk
thunk (IO [Thunk] -> IO Thunk) -> IO [Thunk] -> IO Thunk
forall a b. (a -> b) -> a -> b
$ p -> IO ()
forall p x. Propagator p x => p -> IO ()
freezeProp p
p IO () -> IO [Thunk] -> IO [Thunk]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Thunk] -> IO [Thunk]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Thunk]
ts2
Purify p -> IO (Purify p)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (p -> Thunk -> Thunk -> Purify p
forall p. p -> Thunk -> Thunk -> Purify p
Purify p
p Thunk
t1 Thunk
t2)
def1 :: (Propagator pa a, Propagator pb b) =>
(pa -> pb -> IO ()) ->
Purify pa -> Purify pb
def1 :: forall pa a pb b.
(Propagator pa a, Propagator pb b) =>
(pa -> pb -> IO ()) -> Purify pa -> Purify pb
def1 pa -> pb -> IO ()
def Purify pa
r1 = [Thunk] -> [Thunk] -> (pb -> IO ()) -> Purify pb
forall p a.
Propagator p a =>
[Thunk] -> [Thunk] -> (p -> IO ()) -> Purify p
new [Purify pa -> Thunk
forall p. Purify p -> Thunk
pre Purify pa
r1] [Purify pa -> Thunk
forall p. Purify p -> Thunk
post Purify pa
r1] ((pb -> IO ()) -> Purify pb) -> (pb -> IO ()) -> Purify pb
forall a b. (a -> b) -> a -> b
$ \pb
p -> do
pa -> pb -> IO ()
def (Purify pa -> pa
forall p. Purify p -> p
prop Purify pa
r1) pb
p
def2 :: (Propagator pa a, Propagator pb b, Propagator pc c) =>
(pa -> pb -> pc -> IO ()) ->
Purify pa -> Purify pb -> Purify pc
def2 :: forall pa a pb b pc c.
(Propagator pa a, Propagator pb b, Propagator pc c) =>
(pa -> pb -> pc -> IO ()) -> Purify pa -> Purify pb -> Purify pc
def2 pa -> pb -> pc -> IO ()
def Purify pa
r1 Purify pb
r2 = [Thunk] -> [Thunk] -> (pc -> IO ()) -> Purify pc
forall p a.
Propagator p a =>
[Thunk] -> [Thunk] -> (p -> IO ()) -> Purify p
new [Purify pa -> Thunk
forall p. Purify p -> Thunk
pre Purify pa
r1, Purify pb -> Thunk
forall p. Purify p -> Thunk
pre Purify pb
r2] [Purify pa -> Thunk
forall p. Purify p -> Thunk
post Purify pa
r1, Purify pb -> Thunk
forall p. Purify p -> Thunk
post Purify pb
r2] ((pc -> IO ()) -> Purify pc) -> (pc -> IO ()) -> Purify pc
forall a b. (a -> b) -> a -> b
$ \pc
p -> do
pa -> pb -> pc -> IO ()
def (Purify pa -> pa
forall p. Purify p -> p
prop Purify pa
r1) (Purify pb -> pb
forall p. Purify p -> p
prop Purify pb
r2) pc
p
defList :: (Propagator pa a, Propagator pb b) =>
([pa] -> pb -> IO ()) ->
[Purify pa] -> Purify pb
defList :: forall pa a pb b.
(Propagator pa a, Propagator pb b) =>
([pa] -> pb -> IO ()) -> [Purify pa] -> Purify pb
defList [pa] -> pb -> IO ()
def [Purify pa]
rs = [Thunk] -> [Thunk] -> (pb -> IO ()) -> Purify pb
forall p a.
Propagator p a =>
[Thunk] -> [Thunk] -> (p -> IO ()) -> Purify p
new ((Purify pa -> Thunk) -> [Purify pa] -> [Thunk]
forall a b. (a -> b) -> [a] -> [b]
map Purify pa -> Thunk
forall p. Purify p -> Thunk
pre [Purify pa]
rs) ((Purify pa -> Thunk) -> [Purify pa] -> [Thunk]
forall a b. (a -> b) -> [a] -> [b]
map Purify pa -> Thunk
forall p. Purify p -> Thunk
post [Purify pa]
rs) ((pb -> IO ()) -> Purify pb) -> (pb -> IO ()) -> Purify pb
forall a b. (a -> b) -> a -> b
$ \pb
p -> do
[pa] -> pb -> IO ()
def ((Purify pa -> pa) -> [Purify pa] -> [pa]
forall a b. (a -> b) -> [a] -> [b]
map Purify pa -> pa
forall p. Purify p -> p
prop [Purify pa]
rs) pb
p
get :: Propagator pa a => Purify pa -> a
get :: forall pa a. Propagator pa a => Purify pa -> a
get Purify pa
r = IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
Thunk -> IO ()
force (Purify pa -> Thunk
forall p. Purify p -> Thunk
pre Purify pa
r)
Thunk -> IO ()
force (Purify pa -> Thunk
forall p. Purify p -> Thunk
post Purify pa
r)
pa -> IO a
forall p x. Propagator p x => p -> IO x
readProp (Purify pa -> pa
forall p. Purify p -> p
prop Purify pa
r)