circuits-agent
Safe HaskellNone
LanguageGHC2024

Circuit.Agent.Framing

Description

Bus message framing.

Storage format is JSON Lines: one stamped Post per line with fields id, ts, from, to, thread and body. The body is never mutated for framing; JSON string encoding handles newlines in the standard way.

The file image is a stream with the same Stream ends as the pure log: Log is oldest-first on disk, so append is snoc and read is uncons. The pure Log is newest-first; that is the dual linearisation of the same thread DAG, not a different algebra.

'Log a' stores 'Stamped a' values in memory — no encoding in the hot path. File persistence uses frameStored/unframeStored via PostBody at the storage boundary.

Backwards compatibility: parseLineAt also accepts the legacy flat triple {"ts":..., "sender":..., "body":...} and the bracket format [timestamp] sender: body so existing log files remain readable. Those legacy lines are assigned the supplied line index as their id and empty to/thread lists.

Synopsis

Types

type PostId = Natural Source #

Absolute post identity. In the stamped log this is the line id assigned by the single writer. In pure meeting logs it is the position in the oldest-first log, but branches and cone resolve by the id itself, not by position in the passed-in list. Use indexToIdMap to assign ids [0..] from a chronological list.

class PostBody a where Source #

Encodable/decodable post body. Every body type in the bus must support JSON round-trip through 'circuits-parser''s Json type.

Instances

Instances details
PostBody Text Source # 
Instance details

Defined in Circuit.Agent.Framing

type Stamped a = Stamped (UTCTime, PostId) (Post a) Source #

Storage boundary: a post with its assigned id and timestamp.

This is the agent-side specialisation of Stamped from circuits core: the occurrence token is the (UTCTime, PostId) pair and the payload is a Post a. The core type carries the free theorem that fmap cannot touch the stamp, so the agent shares it rather than duplicating it.

pattern Stamped :: (UTCTime, PostId) -> Post a -> Stamped a Source #

The core Stamped constructor specialised to the agent's occurrence token (UTCTime, PostId).

stamp :: Stamped r a -> r #

Occurrence token / receipt. Not touched by fmap.

stamped :: Stamped r a -> a #

The labelled payload.

newtype Log a Source #

The log image: a stream of stamped posts, oldest first.

Constructors

Log 

Fields

Instances

Instances details
Functor Log Source # 
Instance details

Defined in Circuit.Agent.Framing

Methods

fmap :: (a -> b) -> Log a -> Log b #

(<$) :: a -> Log b -> Log a #

Eq a => Eq (Log a) Source # 
Instance details

Defined in Circuit.Agent.Framing

Methods

(==) :: Log a -> Log a -> Bool #

(/=) :: Log a -> Log a -> Bool #

Show a => Show (Log a) Source # 
Instance details

Defined in Circuit.Agent.Framing

Methods

showsPrec :: Int -> Log a -> ShowS #

show :: Log a -> String #

showList :: [Log a] -> ShowS #

Cons (Log a) (Stamped a) Source #

Prepend is the dual view: a newest-first stream over the same image.

Instance details

Defined in Circuit.Agent.Framing

Methods

cons :: Stamped a -> Log a -> Log a #

consNil :: Log a #

Snoc (Log a) (Stamped a) Source #

Append is the natural operation: one element at the end.

Instance details

Defined in Circuit.Agent.Framing

Methods

snoc :: Log a -> Stamped a -> Log a #

snocNil :: Log a #

Uncons (Log a) (Stamped a) Source #

Read peels the oldest element first.

Instance details

Defined in Circuit.Agent.Framing

Methods

uncons :: Log a -> These (Stamped a) (Log a) #

nil :: Log a #

Stream ends (re-exported from Circuit.Stream)

class Cons f s where #

Stream algebra: construct a stream by prepending one token on the left.

This is the construction dual of Uncons. Together they let code move back and forth between tokens and streams using the same coalgebra.

Methods

cons :: s -> f -> f #

Prepend one token to the left of a stream.

consNil :: f #

The empty stream.

Instances

Instances details
Cons [a] a # 
Instance details

Defined in Circuit.Stream

Methods

cons :: a -> [a] -> [a] #

consNil :: [a] #

Cons (Log a) (Stamped a) Source #

Prepend is the dual view: a newest-first stream over the same image.

Instance details

Defined in Circuit.Agent.Framing

Methods

cons :: Stamped a -> Log a -> Log a #

consNil :: Log a #

Cons (Array a) (Array a) #

Prepend a row. When the tail is the empty stream, construct a one-row array from the row's shape.

Instance details

Defined in Circuit.Mat.Array.Stream

Methods

cons :: Array a -> Array a -> Array a #

consNil :: Array a #

class Snoc f s where #

Stream algebra: construct a stream by appending one token on the right.

This is the right-handed dual of Uncons.

Methods

snoc :: f -> s -> f #

Append one token to the right of a stream.

snocNil :: f #

The empty stream.

Instances

Instances details
Snoc [a] a # 
Instance details

Defined in Circuit.Stream

Methods

snoc :: [a] -> a -> [a] #

snocNil :: [a] #

Snoc (Log a) (Stamped a) Source #

Append is the natural operation: one element at the end.

Instance details

Defined in Circuit.Agent.Framing

Methods

snoc :: Log a -> Stamped a -> Log a #

snocNil :: Log a #

Snoc (Array a) (Array a) #

Append a row. When the initial stream is empty, construct a one-row array from the row's shape.

Instance details

Defined in Circuit.Mat.Array.Stream

Methods

snoc :: Array a -> Array a -> Array a #

snocNil :: Array a #

class Uncons f s where #

Stream coalgebra with explicit boundary.

uncons [x] = This x announces the final element at extraction. The nil value is the stream-specific empty used to continue after a This result.

Methods

uncons :: f -> These s f #

nil :: f #

Instances

Instances details
Uncons ByteString Word8 # 
Instance details

Defined in Circuit.Parser.Stream

Uncons ByteString Char #

Strict ByteString as a stream of Char.

Warning: bytes >= 0x80 are exposed as raw-byte Chars via toEnum . fromIntegral, not decoded UTF-8. If you parse text content char-wise and convert to String or Text, multibyte characters will mojibake. The safe pattern is to recognise structure byte-wise and decode complete spans once (see the json/csv dialects for examples).

Instance details

Defined in Circuit.Parser.Stream

Uncons Text Char # 
Instance details

Defined in Circuit.Parser.Stream

Methods

uncons :: Text -> These Char Text #

nil :: Text #

Uncons [a] a # 
Instance details

Defined in Circuit.Stream

Methods

uncons :: [a] -> These a [a] #

nil :: [a] #

Uncons (Log a) (Stamped a) Source #

Read peels the oldest element first.

Instance details

Defined in Circuit.Agent.Framing

Methods

uncons :: Log a -> These (Stamped a) (Log a) #

nil :: Log a #

Uncons (Array a) (Array a) #

An array is a stream of its rows.

  • Empty array → That empty
  • One-row array → This row
  • Many-row array → These head tail
Instance details

Defined in Circuit.Mat.Array.Stream

Methods

uncons :: Array a -> These (Array a) (Array a) #

nil :: Array a #

data These a b #

The These type represents values with two non-exclusive possibilities.

This can be useful to represent combinations of two values, where the combination is defined if either input is. Algebraically, the type These A B represents (A + B + AB), which doesn't factor easily into sums and products--a type like Either A (B, Maybe A) is unclear and awkward to use.

These has straightforward instances of Functor, Monad, &c., and behaves like a hybrid error/writer monad, as would be expected.

For zipping and unzipping of structures with These values, see Data.Align.

Constructors

This a 
That b 
These a b 

Instances

Instances details
Bifoldable These # 
Instance details

Defined in Data.These

Methods

bifold :: Monoid m => These m m -> m #

bifoldMap :: Monoid m => (a -> m) -> (b -> m) -> These a b -> m #

bifoldr :: (a -> c -> c) -> (b -> c -> c) -> c -> These a b -> c #

bifoldl :: (c -> a -> c) -> (c -> b -> c) -> c -> These a b -> c #

Bifoldable1 These #

Since: these-1.2

Instance details

Defined in Data.These

Methods

bifold1 :: Semigroup m => These m m -> m #

bifoldMap1 :: Semigroup m => (a -> m) -> (b -> m) -> These a b -> m #

Bifunctor These # 
Instance details

Defined in Data.These

Methods

bimap :: (a -> b) -> (c -> d) -> These a c -> These b d #

first :: (a -> b) -> These a c -> These b c #

second :: (b -> c) -> These a b -> These a c #

Bitraversable These # 
Instance details

Defined in Data.These

Methods

bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> These a b -> f (These c d) #

Eq2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftEq2 :: (a -> b -> Bool) -> (c -> d -> Bool) -> These a c -> These b d -> Bool #

Ord2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftCompare2 :: (a -> b -> Ordering) -> (c -> d -> Ordering) -> These a c -> These b d -> Ordering #

Read2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftReadsPrec2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> Int -> ReadS (These a b) #

liftReadList2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> ReadS [These a b] #

liftReadPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec (These a b) #

liftReadListPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec [These a b] #

Show2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftShowsPrec2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> Int -> These a b -> ShowS #

liftShowList2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> [These a b] -> ShowS #

NFData2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftRnf2 :: (a -> ()) -> (b -> ()) -> These a b -> () #

Hashable2 These #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> These a b -> Int #

Assoc These #

Since: these-0.8

Instance details

Defined in Data.These

Methods

assoc :: These (These a b) c -> These a (These b c) #

unassoc :: These a (These b c) -> These (These a b) c #

Swap These #

Since: these-0.8

Instance details

Defined in Data.These

Methods

swap :: These a b -> These b a #

Monad m => Channel These (K m :: Type -> Type -> Type) #

Inclusive monoidal structure for K m with These.

Instance details

Defined in Circuit.Channel

Methods

assoc :: K m (These (These a b) c) (These a (These b c)) #

assoc' :: K m (These a (These b c)) (These (These a b) c) #

slide :: K m (These a (These b c)) (These b (These a c)) #

Channel These (->) #

Inclusive monoidal structure for These.

These sits above both (,) and Either: This is the residual-only branch, That is the payload-only branch, and These carries both.

Instance details

Defined in Circuit.Channel

Methods

assoc :: These (These a b) c -> These a (These b c) #

assoc' :: These a (These b c) -> These (These a b) c #

slide :: These a (These b c) -> These b (These a c) #

Monad m => Strength These (K m :: Type -> Type -> Type) #

Inclusive tensorial strength for K m with These.

Instance details

Defined in Circuit.Channel

Methods

strength :: K m b c -> K m (These a b) (These a c) #

Strength These (->) #

Inclusive tensorial strength for These.

strength applies the payload morphism to the That branch and the These branch, leaving the This residual branch untouched.

Instance details

Defined in Circuit.Channel

Methods

strength :: (b -> c) -> These a b -> These a c #

Monad m => Action These (K m :: Type -> Type -> Type) #

Inclusive symmetry on K m.

Instance details

Defined in Circuit.Tensor

Methods

braid :: K m (These a b) (These b a) #

Action These (->) #

Inclusive symmetry on functions.

Instance details

Defined in Circuit.Tensor

Methods

braid :: These a b -> These b a #

Monad m => Tensor These (K m :: Type -> Type -> Type) #

Inclusive tensor action on K m.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: K m a b -> K m c d -> K m (These a c) (These b d) #

Tensor These (->) #

Inclusive tensor action on functions.

Instance details

Defined in Circuit.Tensor

Methods

tensor :: (a -> b) -> (c -> d) -> These a c -> These b d #

Monad m => Unital These (K m :: Type -> Type -> Type) #

Inclusive unit structure on K m.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: K m (These (Unit These) a) a #

unitl' :: K m a (These (Unit These) a) #

unitr :: K m (These a (Unit These)) a #

unitr' :: K m a (These a (Unit These)) #

Unital These (->) #

Inclusive unit structure on functions.

Laws: unitl eliminates a vacuous This, unitl' injects with That; unitr eliminates a vacuous That, unitr' injects with This.

Instance details

Defined in Circuit.Tensor

Methods

unitl :: These (Unit These) a -> a #

unitl' :: a -> These (Unit These) a #

unitr :: These a (Unit These) -> a #

unitr' :: a -> These a (Unit These) #

Generic1 (These a :: Type -> Type) # 
Instance details

Defined in Data.These

Methods

from1 :: These a a0 -> Rep1 (These a) a0 #

to1 :: Rep1 (These a) a0 -> These a a0 #

Eq a => Eq1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftEq :: (a0 -> b -> Bool) -> These a a0 -> These a b -> Bool #

Ord a => Ord1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftCompare :: (a0 -> b -> Ordering) -> These a a0 -> These a b -> Ordering #

Read a => Read1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftReadsPrec :: (Int -> ReadS a0) -> ReadS [a0] -> Int -> ReadS (These a a0) #

liftReadList :: (Int -> ReadS a0) -> ReadS [a0] -> ReadS [These a a0] #

liftReadPrec :: ReadPrec a0 -> ReadPrec [a0] -> ReadPrec (These a a0) #

liftReadListPrec :: ReadPrec a0 -> ReadPrec [a0] -> ReadPrec [These a a0] #

Show a => Show1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftShowsPrec :: (Int -> a0 -> ShowS) -> ([a0] -> ShowS) -> Int -> These a a0 -> ShowS #

liftShowList :: (Int -> a0 -> ShowS) -> ([a0] -> ShowS) -> [These a a0] -> ShowS #

NFData a => NFData1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftRnf :: (a0 -> ()) -> These a a0 -> () #

Semigroup a => Applicative (These a) # 
Instance details

Defined in Data.These

Methods

pure :: a0 -> These a a0 #

(<*>) :: These a (a0 -> b) -> These a a0 -> These a b #

liftA2 :: (a0 -> b -> c) -> These a a0 -> These a b -> These a c #

(*>) :: These a a0 -> These a b -> These a b #

(<*) :: These a a0 -> These a b -> These a a0 #

Functor (These a) # 
Instance details

Defined in Data.These

Methods

fmap :: (a0 -> b) -> These a a0 -> These a b #

(<$) :: a0 -> These a b -> These a a0 #

Semigroup a => Monad (These a) # 
Instance details

Defined in Data.These

Methods

(>>=) :: These a a0 -> (a0 -> These a b) -> These a b #

(>>) :: These a a0 -> These a b -> These a b #

return :: a0 -> These a a0 #

Foldable (These a) # 
Instance details

Defined in Data.These

Methods

fold :: Monoid m => These a m -> m #

foldMap :: Monoid m => (a0 -> m) -> These a a0 -> m #

foldMap' :: Monoid m => (a0 -> m) -> These a a0 -> m #

foldr :: (a0 -> b -> b) -> b -> These a a0 -> b #

foldr' :: (a0 -> b -> b) -> b -> These a a0 -> b #

foldl :: (b -> a0 -> b) -> b -> These a a0 -> b #

foldl' :: (b -> a0 -> b) -> b -> These a a0 -> b #

foldr1 :: (a0 -> a0 -> a0) -> These a a0 -> a0 #

foldl1 :: (a0 -> a0 -> a0) -> These a a0 -> a0 #

toList :: These a a0 -> [a0] #

null :: These a a0 -> Bool #

length :: These a a0 -> Int #

elem :: Eq a0 => a0 -> These a a0 -> Bool #

maximum :: Ord a0 => These a a0 -> a0 #

minimum :: Ord a0 => These a a0 -> a0 #

sum :: Num a0 => These a a0 -> a0 #

product :: Num a0 => These a a0 -> a0 #

Traversable (These a) # 
Instance details

Defined in Data.These

Methods

traverse :: Applicative f => (a0 -> f b) -> These a a0 -> f (These a b) #

sequenceA :: Applicative f => These a (f a0) -> f (These a a0) #

mapM :: Monad m => (a0 -> m b) -> These a a0 -> m (These a b) #

sequence :: Monad m => These a (m a0) -> m (These a a0) #

Hashable a => Hashable1 (These a) #

Since: these-1.1.1

Instance details

Defined in Data.These

Methods

liftHashWithSalt :: (Int -> a0 -> Int) -> Int -> These a a0 -> Int #

(Binary a, Binary b) => Binary (These a b) #

Since: these-0.7.1

Instance details

Defined in Data.These

Methods

put :: These a b -> Put #

get :: Get (These a b) #

putList :: [These a b] -> Put #

(NFData a, NFData b) => NFData (These a b) #

Since: these-0.7.1

Instance details

Defined in Data.These

Methods

rnf :: These a b -> () #

(Semigroup a, Semigroup b) => Semigroup (These a b) # 
Instance details

Defined in Data.These

Methods

(<>) :: These a b -> These a b -> These a b #

sconcat :: NonEmpty (These a b) -> These a b #

stimes :: Integral b0 => b0 -> These a b -> These a b #

(Eq a, Eq b) => Eq (These a b) # 
Instance details

Defined in Data.These

Methods

(==) :: These a b -> These a b -> Bool #

(/=) :: These a b -> These a b -> Bool #

(Ord a, Ord b) => Ord (These a b) # 
Instance details

Defined in Data.These

Methods

compare :: These a b -> These a b -> Ordering #

(<) :: These a b -> These a b -> Bool #

(<=) :: These a b -> These a b -> Bool #

(>) :: These a b -> These a b -> Bool #

(>=) :: These a b -> These a b -> Bool #

max :: These a b -> These a b -> These a b #

min :: These a b -> These a b -> These a b #

(Data a, Data b) => Data (These a b) # 
Instance details

Defined in Data.These

Methods

gfoldl :: (forall d b0. Data d => c (d -> b0) -> d -> c b0) -> (forall g. g -> c g) -> These a b -> c (These a b) #

gunfold :: (forall b0 r. Data b0 => c (b0 -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (These a b) #

toConstr :: These a b -> Constr #

dataTypeOf :: These a b -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (These a b)) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (These a b)) #

gmapT :: (forall b0. Data b0 => b0 -> b0) -> These a b -> These a b #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> These a b -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> These a b -> r #

gmapQ :: (forall d. Data d => d -> u) -> These a b -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> These a b -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> These a b -> m (These a b) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> These a b -> m (These a b) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> These a b -> m (These a b) #

Generic (These a b) # 
Instance details

Defined in Data.These

Methods

from :: These a b -> Rep (These a b) x #

to :: Rep (These a b) x -> These a b #

(Read a, Read b) => Read (These a b) # 
Instance details

Defined in Data.These

(Show a, Show b) => Show (These a b) # 
Instance details

Defined in Data.These

Methods

showsPrec :: Int -> These a b -> ShowS #

show :: These a b -> String #

showList :: [These a b] -> ShowS #

(Hashable a, Hashable b) => Hashable (These a b) # 
Instance details

Defined in Data.These

Methods

hashWithSalt :: Int -> These a b -> Int #

hash :: These a b -> Int #

type Unit These # 
Instance details

Defined in Circuit.Tensor

type Unit These = Void
type Rep1 (These a :: Type -> Type) # 
Instance details

Defined in Data.These

type Rep (These a b) # 
Instance details

Defined in Data.These

Encoding

frameStored :: PostBody a => Stamped a -> Text Source #

Encode a 'Stamped a' as a single canonical JSON Lines object.

framePost :: PostBody a => Post a -> Text Source #

Encode a bare 'Post a' as a single JSON Lines object (the protocol format sent to the stamping bus daemon).

Parsing

unframeStored :: PostBody a => Text -> Maybe (Stamped a) Source #

Unframe a canonical stamped storage line (the inverse of frameStored). Returns Nothing if the line is not valid JSON with the expected fields.

parseLineAt :: Int -> Text -> Maybe (Stamped Text) Source #

Like unframeStored, but also accepts the legacy flat triple and bracket formats, assigning the supplied line index as the id. Legacy-only, Text body.

parsePost :: PostBody a => Text -> Maybe (Post a) Source #

Parse a bare 'Post a' line (no stamp).

parseMessage :: Text -> Maybe (Text, Text) Source #

Parse a raw log line into (from, body), accepting the stamped format and both legacy formats.

parseMessageTs :: Text -> Maybe Text Source #

Extract just the timestamp from a raw log line.

Rendering

renderStored :: PostBody a => Stamped a -> Text Source #

Render a 'Stamped a' for human display as [idts] from: body@.

renderMessage :: Text -> Maybe Text Source #

Render a raw log line for human display.

Time

formatNow :: IO Text Source #

Current UTC time as an ISO-8601 string.

parseTimeText :: Text -> Maybe UTCTime Source #

Parse an ISO-8601 string to UTCTime, accepting the format we write.

File helpers

readLogFile :: PostBody a => FilePath -> IO (Log a) Source #

Read a log file into a 'Log a', oldest first. Malformed lines are skipped.

encodeLog :: PostBody a => Log a -> [Text] Source #

Encode a 'Log a' to raw JSONL text for file persistence.