packages feed

creditmonad-1.0.0: src/Test/Credit/Queue/Realtime.hs

module Test.Credit.Queue.Realtime where

import Prelude hiding (lookup, reverse)

import Prettyprinter (Pretty)
import Control.Monad.Credit
import Test.Credit.Queue.Base
import Test.Credit.Queue.Streams

-- | Delay a computation, but do not consume any credits
indirect :: MonadInherit m => SLazyCon m (Stream m a) -> m (Stream m a)
indirect t = delay t >>= pure . SIndirect

data RQueue a m = RQueue
  { front :: Stream m a
  , rear :: Stream m a
  , schedule :: Stream m a
  }

rqueue :: MonadInherit m => RQueue a m -> m (RQueue a m)
rqueue (RQueue f r s) = credit s >> credit s >> smatch s
  (\x s -> pure $ RQueue f r s)
  (do
    r' <- indirect (SReverse r SNil)
    f' <- indirect (SAppend f r')
    credit r' >> evalone r'
    pure $ RQueue f' SNil f')

instance Queue RQueue where
  empty = pure $ RQueue SNil SNil SNil
  snoc (RQueue f r s) x = rqueue (RQueue f (SCons x r) s)
  uncons (RQueue f r s) = credit f >> credit f >> smatch f
    (\x f -> rqueue (RQueue f r s) >>= \q -> pure $ Just (x, q))
    (pure Nothing)

instance BoundedQueue RQueue where
  qcost _ (Snoc _) = 4
  qcost _ Uncons = 7

instance (MonadMemory m, MemoryCell m a) => MemoryCell m (RQueue a m) where
  prettyCell (RQueue f r s) = do
    f' <- prettyCell f
    r' <- prettyCell r
    s' <- prettyCell s
    pure $ mkMCell "Queue" [f', r', s']

instance Pretty a => MemoryStructure (RQueue (PrettyCell a)) where
  prettyStructure = prettyCell