| 1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
|---|
| 2 | |
|---|
| 3 | import Control.Applicative |
|---|
| 4 | import Control.Monad |
|---|
| 5 | import Control.Monad.Fix |
|---|
| 6 | import Data.IORef |
|---|
| 7 | import Data.Maybe |
|---|
| 8 | import Prelude hiding (until) |
|---|
| 9 | import System.Mem.Weak |
|---|
| 10 | |
|---|
| 11 | newtype Signal a = S (IO a) deriving (Functor, Applicative, Monad) |
|---|
| 12 | type UpdatePool = [Weak (IO (), IO ())] |
|---|
| 13 | newtype SignalGen a = SG { unSG :: IORef UpdatePool -> IO a } |
|---|
| 14 | data Phase a = Ready a | Updated a a |
|---|
| 15 | |
|---|
| 16 | instance Functor SignalGen where |
|---|
| 17 | fmap = liftM |
|---|
| 18 | |
|---|
| 19 | instance Applicative SignalGen where |
|---|
| 20 | pure = return |
|---|
| 21 | (<*>) = ap |
|---|
| 22 | |
|---|
| 23 | instance Monad SignalGen where |
|---|
| 24 | return x = SG $ \_ -> return x |
|---|
| 25 | SG g >>= f = SG $ \p -> g p >>= \x -> unSG (f x) p |
|---|
| 26 | |
|---|
| 27 | instance MonadFix SignalGen where |
|---|
| 28 | mfix f = SG $ \p -> mfix $ \x -> unSG (f x) p |
|---|
| 29 | |
|---|
| 30 | start :: SignalGen (Signal a) -- ^ the generator of the top-level signal |
|---|
| 31 | -> IO (IO a) -- ^ the computation to sample the signal |
|---|
| 32 | start (SG gen) = do |
|---|
| 33 | pool <- newIORef [] |
|---|
| 34 | S sample <- gen pool |
|---|
| 35 | return $ do |
|---|
| 36 | print "res <- sample" |
|---|
| 37 | res <- sample |
|---|
| 38 | print "superstep pool" |
|---|
| 39 | superstep pool |
|---|
| 40 | print "return res" |
|---|
| 41 | return res |
|---|
| 42 | |
|---|
| 43 | -- | Performing the two-phase superstep. |
|---|
| 44 | superstep :: IORef UpdatePool -> IO () |
|---|
| 45 | superstep pool = loop id [] |
|---|
| 46 | where |
|---|
| 47 | deref ptr = (fmap.fmap) ((,) ptr) (deRefWeak ptr) |
|---|
| 48 | loop getPtrs final = do |
|---|
| 49 | print "(ptrs,acts) <- unzip.catMaybes <$> (mapM deref =<< readIORef pool)" |
|---|
| 50 | (ptrs,acts) <- unzip.catMaybes <$> (mapM deref =<< readIORef pool) |
|---|
| 51 | print "case acts of" |
|---|
| 52 | case acts of |
|---|
| 53 | [] -> do |
|---|
| 54 | print "[] -> do sequence_ final" |
|---|
| 55 | sequence_ final |
|---|
| 56 | print "writeIORef pool (getPtrs []" |
|---|
| 57 | writeIORef pool (getPtrs []) |
|---|
| 58 | print "done: writeIORef pool (getPtrs []" |
|---|
| 59 | _ -> do |
|---|
| 60 | print "_ -> do writeIORef pool []" |
|---|
| 61 | writeIORef pool [] |
|---|
| 62 | print "mapM_ fst acts" |
|---|
| 63 | mapM_ fst acts |
|---|
| 64 | print "loop ((ptrs++) . getPtrs) (mapM_ snd acts : final)" |
|---|
| 65 | loop ((ptrs++) . getPtrs) (mapM_ snd acts : final) |
|---|
| 66 | print "done: loop ((ptrs++) . getPtrs) (mapM_ snd acts : final)" |
|---|
| 67 | |
|---|
| 68 | delay :: a -- ^ initial output at creation time |
|---|
| 69 | -> Signal a -- ^ the signal to delay |
|---|
| 70 | -> SignalGen (Signal a) -- ^ the delayed signal |
|---|
| 71 | delay x0 (S s) = SG $ \pool -> do |
|---|
| 72 | print "ref <- newIORef (Ready x0)" |
|---|
| 73 | ref <- newIORef (Ready x0) |
|---|
| 74 | let update x = print "s >>= \\x' -> x' `seq`" >> s >>= \x' -> x' `seq` (print " writeIORef ref (Updated x' x)" >> writeIORef ref (Updated x' x)) |
|---|
| 75 | upd = print "readIORef ref >>= \v -> case v of" >> readIORef ref >>= \v -> case v of |
|---|
| 76 | Ready x -> print "Ready x -> update x" >> update x |
|---|
| 77 | _ -> print "_ -> return ()" >> return () |
|---|
| 78 | |
|---|
| 79 | fin = print "readIORef ref >>= \v -> case v o" >> readIORef ref >>= \v -> case v of |
|---|
| 80 | Updated x _ -> print "Updated x _ -> writeIORef ref $! Ready x" >> (writeIORef ref $! Ready x) |
|---|
| 81 | _ -> error "Signal not updated!" |
|---|
| 82 | |
|---|
| 83 | sig = S $ print "readIORef ref >>= \v -> case v of" >> readIORef ref >>= \v -> case v of |
|---|
| 84 | Ready x -> print "Ready x -> return x" >> return x |
|---|
| 85 | Updated _ x -> print "Updated _ x -> return x" >> return x |
|---|
| 86 | print "updateActions <- mkWeak sig (upd,fin) Nothing" |
|---|
| 87 | updateActions <- mkWeak sig (upd,fin) Nothing |
|---|
| 88 | print "modifyIORef pool (updateActions:)" |
|---|
| 89 | modifyIORef pool (updateActions:) |
|---|
| 90 | print "return sig" |
|---|
| 91 | return sig |
|---|
| 92 | |
|---|
| 93 | |
|---|
| 94 | stateful :: a -- ^ initial state |
|---|
| 95 | -> (a -> a) -- ^ state transformation |
|---|
| 96 | -> SignalGen (Signal a) |
|---|
| 97 | stateful x0 f = mfix $ \sig -> delay x0 (f <$> sig) |
|---|
| 98 | |
|---|
| 99 | main = do |
|---|
| 100 | net <- start $ stateful 0 (1+) |
|---|
| 101 | print "1st iteration" |
|---|
| 102 | net -- ok for first time |
|---|
| 103 | print "2nd iteration" |
|---|
| 104 | net -- error: thread blocked indefinitely in an MVar operation |
|---|