Source code on Github
open import Prelude.Init

open import UTxO.Hashing
open import UTxO.Value
open import UTxO.Types

open import StateMachine.Base

module StateMachine.Inductive.Combinators
  {S I : Set} {{_ : IsData S}} {{_ : IsData I}} {sm : StateMachine S I}
  where

open CEM {sm = sm}
open import StateMachine.Inductive.Core {sm = sm}

-- *** All ***

-- the predicate P holds for all states in the run
data AllS (P : S → Set) : ∀{s s'} → s ↝⋆ s' → Set where
  root : ∀ {s} (p : Init s)
    → P s
    → AllS P (root p)
  snoc : ∀ {s s' s''} (p : s ↝⋆ s')(q : s' ↝ s'')
    → P s''
    → AllS P p → AllS P (snoc p q)

-- the property holds in the end
end : ∀ P {s s'}{p : s ↝⋆ s'} → AllS P p → P s'
end P (root p q) = q
end P (snoc p q r s) = r

all-lem : (P : S → Set)
        → (∀{s} → Init s → P s)
        → (∀{s s'} → s ↝ s' → P s → P s')
        → ∀ {s s'}(p : s ↝⋆ s') → AllS P p
all-lem P base step (root p) = root p (base p)
all-lem P base step (snoc p q) =
  snoc p q (step q (end P h)) h
  where h = all-lem P base step p

-- properties of inputs (which may refer to the other stuff)
data AllI (P₀ : S → Set) (P : S → I → TxConstraints → S → Set) : ∀ {s s'} → s ↝⋆ s' → Set where
  root : ∀ {s} (p : Init s)
    → P₀ s
    → AllI P₀ P (root p)
  snoc : ∀ {s s' s'' } (p : s ↝⋆ s')(q : s' ↝ s'')
    → P s' (proj₁ q) (proj₁ $ proj₂ q) s''
    → AllI P₀ P p → AllI P₀ P (snoc p q)

-- *** Any ***

data AnyS (P : S → Set) : ∀{s s'} → s ↝⋆ s' → Set where

  root : ∀ {s} (p : Init s)
    → P s
    → AnyS P (root p)

  here : ∀ {s s' s''} (p : s ↝⋆ s')(q : s' ↝ s'')
    → P s''
    → AnyS P (snoc p q)

  there : ∀ {s s' s''} (p : s ↝⋆ s')(q : s' ↝ s'')
    → AnyS P p
    → AnyS P (snoc p q)
-- TODO: this isn't right, it needs two snoctructors for root

-- *** Until ***

-- P+Q*
-- P holds and then Q holds

-- * P has to hold at least at the initial state, it can hold forever
-- and then Q doesn't need to hold at all

-- * if Q takes over then P does not need to hold anymore. There is no
-- enforced overlap

data UntilS (P Q : S → Set) : ∀{s s'} → s ↝⋆ s' → Set where
  prefix : ∀{s s'}(xs : s ↝⋆ s')
    → AllS P xs
    → UntilS P Q xs

  suffix : ∀{s s' s''}(xs : s ↝⋆ s')
    → UntilS P Q xs
    → (x : s' ↝ s'')
    → Q s''
    → UntilS P Q (snoc xs x)