-- | Ways to merge parallel judgments (beyond raw lattice meet/join).
--
-- Lattice ops are available via "Circuit.Logics.Lattice". Protocol-style
-- combinators live here — especially useful for multi-judge @Process@ wiring.
module Circuit.Logics.Combine
  ( consensusH3,
    consensusK3,
    firstKnownH3,
    latchH3,
  )
where

import Circuit.Logics.H3 (H3 (..))
import Circuit.Logics.K3 (K3 (..))

-- | Agree only when both sides are the same decided value; else unknown.
--
-- Not lattice meet: @consensusH3 HTrue HFalse = HUnknown@, whereas
-- meet would be @HFalse@.
consensusH3 :: H3 -> H3 -> H3
consensusH3 :: H3 -> H3 -> H3
consensusH3 H3
HTrue H3
HTrue = H3
HTrue
consensusH3 H3
HFalse H3
HFalse = H3
HFalse
consensusH3 H3
_ H3
_ = H3
HUnknown

consensusK3 :: K3 -> K3 -> K3
consensusK3 :: K3 -> K3 -> K3
consensusK3 K3
KTrue K3
KTrue = K3
KTrue
consensusK3 K3
KFalse K3
KFalse = K3
KFalse
consensusK3 K3
_ K3
_ = K3
KUnknown

-- | Prefer the first decided value; unknown only if both open.
firstKnownH3 :: H3 -> H3 -> H3
firstKnownH3 :: H3 -> H3 -> H3
firstKnownH3 H3
HUnknown H3
y = H3
y
firstKnownH3 H3
x H3
_ = H3
x

-- | Once decided, stay decided (left-biased latch over a stream step).
latchH3 :: H3 -> H3 -> H3
latchH3 :: H3 -> H3 -> H3
latchH3 H3
HUnknown H3
y = H3
y
latchH3 H3
x H3
_ = H3
x