Temporal Types and Functional Reactive Programming
Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
Two defects hide behind the innocent type 𝖲𝗍𝗋𝖾𝖺𝗆𝐴→𝖲𝗍𝗋𝖾𝖺𝗆𝐵. A function may inspect tomorrow’s input to produce today’s output, violating causality. A causal definition may also retain every old input behind delayed closures, producing an implicit space leak. Ordinary function types express neither prohibition. Simply RaTT separates stable data, the present instant, and the next instant in the typing context, then gives those restrictions an abstract machine [BGM19].
The leak and the lookahead
Write a stream informally as 𝑎0,𝑎1,𝑎2,…. The specification 𝑦𝑛=𝑥𝑛+𝑥𝑛+1 is productive as a mathematical stream equation, but it is not causal: the first output depends on an input not yet received. By contrast, running sum is causal: 𝑦0=𝑥0,𝑦𝑛+1=𝑦𝑛+𝑥𝑛+1. Yet an implementation that keeps the entire prefix [𝑥0,…,𝑥𝑛] to compute 𝑦𝑛 consumes unbounded space for no semantic reason. Causality and bounded reactive memory are separate obligations.
Jeffrey’s LTL presentation gives temporal propositions computational content: next and always types delimit when a reactive value is available [Jef12]. It establishes the temporal discipline needed to reject lookahead. It does not, by that fact alone, forbid a delayed closure from retaining an old heap. Simply RaTT’s contribution is the combination of a Fitch discipline and a machine that discards the old heap at each stream step.
The exact comparison is semantic. If 𝐴[𝑠,𝑢] means that the reactive proposition 𝐴 holds throughout the interval from 𝑠 through 𝑢, Jeffrey’s non-strict constrains type is interpreted by 𝖢𝗈𝗇(𝐴,𝐵)(𝑠)=∏𝑢≥𝑠(𝐴[𝑠,𝑢]→𝐵(𝑢)). An inhabitant can compute the output at 𝑢 from the input history only through 𝑢, which is the causal-function interface. Because the reactive types of Figures 3–5 are the direct interval semantics of LTL, a closed inhabitant of the interpretation of a formula 𝐹 makes 𝐹 valid, under the paper’s stated assumption that the ambient dependent type theory is sound for classical logic. This is temporal soundness, not a storage theorem.
Types include ordinary sums, products, naturals, functions, guarded recursive types, the later type◯𝐴, and the stable modality◻𝐴. Contexts are ordered lists containing assumptions and two tokens. The later modality follows Nakano’s guarded-recursion idea; the Fitch rules and metatheorems below are those of Simply RaTT, not theorem transfers from Nakano’s calculus [Nak00]: Γ::=⋅∣Γ,𝑥:𝐴∣Γ,▸∣Γ,✓. There is at most one lock and one tick; a tick may occur only to the right of a lock. A suffix is token-free when it contains neither token, and a context is tick-free when it contains no tick. The variable and function rules reveal why order matters:
tokenFree(Γ′)
Γ,𝑥:𝐴,Γ′⊢𝑥:𝐴
RaTT-Var
Γ,𝑥:𝐴⊢𝑡:𝐵tickFree(Γ)
Γ⊢𝜆𝑥.𝑡:𝐴→𝐵
RaTT-Abs
Γ⊢𝑡:𝐴→𝐵Γ⊢𝑢:𝐴
Γ⊢𝑡𝑢:𝐵
RaTT-App
Rule RaTT-Var makes assumptions to the left of a temporal token inaccessible. Rule RaTT-Abs prevents a function closure from capturing a current-time assumption beneath a tick.
The modal rules are
Γ,✓⊢𝑡:𝐴
Γ⊢𝖽𝖾𝗅𝖺𝗒𝑡:◯𝐴
RaTT-Delay
Γ⊢𝑡:◯𝐴Γ,✓,Γ′𝖼𝗍𝗑
Γ,✓,Γ′⊢𝖺𝖽𝗏𝑡:𝐴
RaTT-Adv
Γ,▸⊢𝑡:𝐴
Γ⊢𝖻𝗈𝗑𝑡:◻𝐴
RaTT-Box
Γ′⊢𝑡:◻𝐴tokenFree(Γ″)
Γ′,▸,Γ″⊢𝗎𝗇𝖻𝗈𝗑𝑡:𝐴
RaTT-Unbox
Delay closes a term checked one tick later. Advance opens such a term only after that tick has arrived. Boxing moves code behind the lock; unboxing may cross a lock but not another temporal token in its suffix.
A type is stable when it is generated by 1,𝖭𝖺𝗍,◻𝐴,𝐴×𝐵,𝐴+𝐵 with stable components. Function and later types are deliberately absent. Boxed types may nevertheless enclose an arbitrary type, because their terms are checked behind the lock. Stable values may be carried across a tick by
Γ⊢𝑡:𝐴𝐴𝗌𝗍𝖺𝖻𝗅𝖾Γ,✓,Γ′𝖼𝗍𝗑
Γ,✓,Γ′⊢𝗉𝗋𝗈𝗀𝗋𝖾𝗌𝗌𝑡:𝐴
RaTT-Progress
Γ⊢𝑡:𝐴𝐴𝗌𝗍𝖺𝖻𝗅𝖾Γ,▸,Γ′𝖼𝗍𝗑
Γ,▸,Γ′⊢𝗉𝗋𝗈𝗆𝗈𝗍𝖾𝑡:𝐴
RaTT-Promote
Progress carries stable data across a tick; promote makes stable initial data available to the right of the lock. Neither rule permits an arbitrary closure containing the current heap.
★★☆ Assume 𝑥:𝐴 occurs immediately to the left of ✓. Attempt to type 𝜆𝑧.𝑥 after the tick. Name the failed premise. Repeat when 𝑥 has stable type and is moved with 𝗉𝗋𝗈𝗀𝗋𝖾𝗌𝗌.
Guarded recursive types have explicit fold and unfold operations. Define 𝖲𝗍𝗋𝐴:=𝜇𝛼.𝐴×◯𝛼. The recursive occurrence is below later. A stream cell is therefore available now, while its tail becomes available after one tick. The fixed point rule Γ,▸,𝑥:◯𝐴⊢𝑡:𝐴Γ⊢𝖿𝗂𝗑𝑥.𝑡:◻𝐴RaTT−Fix gives recursive code only a delayed self-reference.
For a closed stable function 𝑓:◻(𝐴→𝐵), stream mapping has type 𝗆𝖺𝗉:◻(𝐴→𝐵)→◻(𝖲𝗍𝗋𝐴→𝖲𝗍𝗋𝐵),𝗆𝖺𝗉𝑓=𝖿𝗂𝗑𝑚.𝜆𝑠.𝗅𝖾𝗍(𝑎,𝑠′)=𝗈𝗎𝗍𝑠𝗂𝗇𝗂𝗇𝗍𝗈((𝗎𝗇𝖻𝗈𝗑𝑓)𝑎,𝖽𝖾𝗅𝖺𝗒((𝖺𝖽𝗏𝑚)(𝖺𝖽𝗏𝑠′))). The two advances occur together after the same tick: both the recursive program and the input tail are then available. There is no derivation for a version that advances the input tail before producing the head.
Running sum carries a stable natural accumulator. Its recursive worker has type 𝗌𝗎𝗆′:◻(𝖭𝖺𝗍→𝖲𝗍𝗋𝖭𝖺𝗍→𝖲𝗍𝗋𝖭𝖺𝗍),𝗌𝗎𝗆′=𝖿𝗂𝗑𝑓.𝜆𝑛.𝜆𝑠.𝗅𝖾𝗍(𝑥,𝑠′)=𝗈𝗎𝗍𝑠𝗂𝗇𝗂𝗇𝗍𝗈(𝑛+𝑥,𝖽𝖾𝗅𝖺𝗒((𝖺𝖽𝗏𝑓)(𝗉𝗋𝗈𝗀𝗋𝖾𝗌𝗌(𝑛+𝑥))(𝖺𝖽𝗏𝑠′))). Inside the delay, the recursive code and tail advance together, while the new accumulator crosses the tick by RaTT-Progress. The input cell does not cross it.
The source library makes switching explicit. Define events by 𝖤𝗏𝐴≅𝖾𝗏𝐴+◯(𝖤𝗏𝐴), with constructors 𝗏𝖺𝗅 and 𝗐𝖺𝗂𝗍. Then 𝗌𝗐𝗂𝗍𝖼𝗁:◻(𝖲𝗍𝗋𝐴→𝖤𝗏(𝖲𝗍𝗋𝐴)→𝖲𝗍𝗋𝐴) is defined as 𝖿𝗂𝗑𝑠𝑤.𝜆𝑠.𝜆𝑒.…. Its two body branches are 𝖻𝗈𝖽𝗒𝑠𝑤(𝑥::𝑥𝑠)(𝗐𝖺𝗂𝗍𝑓𝑎𝑠)=𝑥::𝖽𝖾𝗅𝖺𝗒((𝖺𝖽𝗏𝑠𝑤)(𝖺𝖽𝗏𝑥𝑠)(𝖺𝖽𝗏𝑓𝑎𝑠)),𝖻𝗈𝖽𝗒𝑠𝑤𝑥𝑠(𝗏𝖺𝗅𝑦𝑠)=𝑦𝑠. Before an event arrives, the current head is emitted and every tail advances under one delay. A present event may replace the stream immediately; no future event is inspected to choose the current head.
Sampling is a flow operation, not deletion of ticks. Let 𝖢𝗅𝗈𝖼𝗄:=𝖲𝗍𝗋𝖡𝗈𝗈𝗅,𝖥𝗅𝗈𝗐𝐴:=𝖲𝗍𝗋(𝖬𝖺𝗒𝖻𝖾𝐴). The source’s sampler first constructs a slower clock 𝖾𝗏𝖾𝗋𝗒𝖭𝗍𝗁:𝖭𝖺𝗍→◻(𝖢𝗅𝗈𝖼𝗄→𝖢𝗅𝗈𝖼𝗄) by carrying a stable counter, and then masks a flow by 𝗐𝗁𝖾𝗇:◻(𝖢𝗅𝗈𝖼𝗄→𝖥𝗅𝗈𝗐𝐴→𝖥𝗅𝗈𝗐𝐴). Inside 𝗐𝗁𝖾𝗇=𝖿𝗂𝗑𝑤.𝜆𝑐.𝜆𝑎.…, the body is 𝖻𝗈𝖽𝗒𝑤(𝑐::𝑐𝑠)(𝑎::𝑎𝑠)=(𝗂𝖿𝑐𝗍𝗁𝖾𝗇𝑎𝖾𝗅𝗌𝖾𝗇𝗈𝗍𝗁𝗂𝗇𝗀)::𝖽𝖾𝗅𝖺𝗒((𝖺𝖽𝗏𝑤)(𝖺𝖽𝗏𝑐𝑠)(𝖺𝖽𝗏𝑎𝑠)). Thus a slow clock produces 𝗇𝗈𝗍𝗁𝗂𝗇𝗀 on skipped global ticks; the result remains a productive stream.
Accumulation is the stable-state combinator 𝗌𝖼𝖺𝗇:𝐵𝗌𝗍𝖺𝖻𝗅𝖾⇒◻(𝐵→𝐴→𝐵)→◻(𝐵→𝖲𝗍𝗋𝐴→𝖲𝗍𝗋𝐵). Its current cell is 𝑏′=𝑓𝑏𝑎, and its delayed call advances the input tail while carrying 𝑏′ by RaTT-Progress. Running sum is 𝗌𝖼𝖺𝗇(𝖻𝗈𝗑(+))0. A complete network is 𝗌𝗎𝗆∘𝖿𝗋𝗈𝗆𝖬𝖺𝗒𝖻𝖾(𝖻𝗈𝗑0)∘𝗐𝗁𝖾𝗇𝖻𝖺𝗌𝗂𝖼𝖢𝗅𝗈𝖼𝗄∘𝗆𝖺𝗉(𝖻𝗈𝗑𝗃𝗎𝗌𝗍). It maps each input to a present flow cell, samples on the basic clock, fills no holes, and accumulates. On (2,11,5,…) its first three outputs are (2,13,18). Replacing 𝖻𝖺𝗌𝗂𝖼𝖢𝗅𝗈𝖼𝗄 by 𝖾𝗏𝖾𝗋𝗒𝖭𝗍𝗁2𝖻𝖺𝗌𝗂𝖼𝖢𝗅𝗈𝖼𝗄 changes which cells are present, but not the one-global-tick cadence. Switch, sampling, and scan all prohibit an ordinary closure over the present heap from entering a delayed tail.
A store is one of ⊥,▸𝜂𝐿,▸𝜂𝑁✓𝜂𝐿. The later heap 𝜂𝐿 receives delayed computations. After a stream step, it becomes the new now heap 𝜂𝑁; the old now heap is discarded. A delay allocates a fresh location in 𝜂𝐿. An advance retrieves a computation from 𝜂𝑁. The tokens in the typing context mirror exactly which heap operations are available.
A closed stream state is a pair of a store and a term. We write (𝜂,𝑡)⟹𝗌(𝑣,𝜂′,𝑡′) when evaluation exposes a head 𝑣, makes the later heap the new now heap, and continues at 𝑡′. A transducer step records an input and an output: (𝜂,𝑡)⟹𝑣/𝑣′𝗍(𝜂′,𝑡′). For the running-sum transducer, the source trace is 𝗋𝗎𝗇𝖲𝗎𝗆(2,11,5)=(2,13,18). After each transition, one natural accumulator and the delayed tail remain; the machine does not retain the consumed input cell.
Use the source’s machine-state typing and heap-indexed logical relation. If a related stream or transducer state takes one machine step, then every location reachable from the related continuation belongs to the new now heap or the new later heap, not to the discarded old now heap.
Proof of Proposition 55.1 — No old-heap reachability
Proof. This is the garbage-collection consequence of the source’s fundamental lemma, not a theorem of the four surface rules alone. The logical relation indexes values and computations by the machine world. Its ◯𝐴 clause places delayed computations in the later component; the successor-world clause moves that component to the new now heap and forgets the old now component. The stable-type lemma says that a related stable value is independent of temporal heap locations. Applying the fundamental lemma to the step therefore leaves no related continuation root in the forgotten component. The world and term relations used in this argument are frozen in section 55.5; the full store-typing and machine induction remain source obligations [BGM19]. ◻
The proposition excludes implicit leaks caused by the temporal machinery. It does not bound explicit stable data. If the language is extended with lists, stable whenever their elements are stable, a program may intentionally append every input to such a list. That list grows, and the extended type system permits it.
★★☆ Modify running sum so that its stable state is a list of all previous inputs. Explain why proposition 55.1 still holds although the program uses unbounded space.
A world records a store shape and a finite sequence of future heap fragments. Write 𝑤⪯𝗐𝑤′ when 𝑤′ extends the current allocations without changing locations already present. For a semantic environment 𝜎, define three relations: 𝑣∈V[[𝐴]]𝐻𝜎,𝑡∈T[[𝐴]]𝐻𝜎,𝛾∈C[[Γ]]𝐻𝜎. The value relation follows type structure. At ◯𝐴, a location must denote a term in T[[𝐴]] at the next index. At ◻𝐴, the value must satisfy V[[𝐴]] at every admissible future world. The term relation requires evaluation to a related value without illegal heap access. The context relation maps each accessible variable to a related value and interprets locks and ticks by the corresponding world transition. The definition is well founded by lexicographic induction on the remaining time index, type size, and the value/term tag.
Proof of Theorem 55.2 — Fundamental Property, Simply RaTT Theorem 6.3
Proof. Induct on the typing derivation. Variables follow from the context relation; products, sums, naturals, abstraction, and application follow from their value clauses and the induction hypotheses. For delay, allocate the premise term in the later heap. Its ticked premise is interpreted at the successor index, so the stored term lies in the later-type clause. For advance, the context’s tick identifies the now heap; retrieve the related stored term and apply its term clause. For box, the lock removes dependence on the current temporal world, so the induction hypothesis holds at every future extension. For unbox, instantiate that universal clause at the current future world. Progress and promote use stability to preserve the value relation across a tick and a lock, respectively. In the fixed-point case, induction on the time index justifies the delayed recursive hypothesis. Fold and unfold use the guarded recursive-type clause. These cases exhaust the typing rules. ◻
The theorem connects syntax to the machine. Productivity and causality are not separate preservation/progress theorems pasted onto the calculus; they are consequences of the stream and transducer instances of the relation.
Let 𝐴 be a value type built from 1, naturals, sums, and products. If ⊢𝑡:◻𝖲𝗍𝗋𝐴, then for every 𝑛 the abstract machine takes 𝑛 stream steps and produces values 𝑣1,…,𝑣𝑛, each typed at 𝐴.
Proof of Theorem 55.3 — Productivity, Simply RaTT Theorem 3.1
Proof. Unbox 𝑡 to obtain a state in the stream relation at index 𝑛. Apply theorem 55.2 to the empty substitution. The stream clause exposes one related head and a tail at index 𝑛−1. Iterate this argument 𝑛 times. The value-type restriction converts semantic membership of each head into ordinary typing at 𝐴. ◻
Let 𝐴 and 𝐵 be value types. A closed term 𝑡:◻(𝖲𝗍𝗋𝐴→𝖲𝗍𝗋𝐵) has an initial state in the source’s transducer relation. If a state lies in its (𝑘+1)-step approximation and receives a typed input 𝑣:𝐴, it takes one transducer step, emits a typed output 𝑣′:𝐵, and its successor lies in the 𝑘-step approximation.
Proof of Theorem 55.4 — Causality, Simply RaTT Theorem 3.2
Proof. Apply the Fundamental Property to the unboxed function and a related input stream whose head is 𝑣. The function and stream clauses yield one output cell before the input tail becomes available. The emitted head belongs to V[[𝐵]], hence is typed at the value type 𝐵. The delayed tails move to the successor world, which lowers the approximation index from 𝑘+1 to 𝑘. No premise supplies a future input cell to the current output, which is the causal dependency claim. ◻
★★★ Identify the different hypotheses in theorem 55.3, theorem 55.4. Explain why productivity of a closed output stream alone does not prove causality of a transducer.
no Simply RaTT machine theorem without a translation
Source-gated temporal resources and flow refinements
Ahman and Žajdela’s 𝜆[𝜏] is a separate fine-grain call-by-value calculus, not an extension theorem for Simply RaTT [A Z24]. Natural-number grades measure time: 𝜏∈ℕ,𝑋,𝑌::=𝑏∣1∣𝑋×𝑌∣𝑋→𝑌!𝜏∣[𝜏]𝑋,Γ::=⋅∣Γ,𝑥:𝑋∣Γ,⟨𝜏⟩. A value of [𝜏]𝑋 is usable only after at least 𝜏 units; a computation of type 𝑋!𝜏 returns an 𝑋 after spending 𝜏 units. The load-bearing rules are
Γ⊢𝑀:𝑋!𝜏Γ,⟨𝜏⟩,𝑥:𝑋⊢𝑁:𝑌!𝜏′
Γ⊢𝗅𝖾𝗍𝑥=𝑀𝗂𝗇𝑁:𝑌!(𝜏+𝜏′)
TR-Let
Γ,⟨𝜏⟩⊢𝑀:𝑋!𝜏′
Γ⊢𝖽𝖾𝗅𝖺𝗒𝜏𝑀:𝑋!(𝜏+𝜏′)
TR-Delay
Γ,⟨𝜏⟩⊢𝑉:𝑋Γ,𝑥:[𝜏]𝑋⊢𝑁:𝑌!𝜏′
Γ⊢𝖻𝗈𝗑[𝜏]𝑉𝖺𝗌𝑥𝗂𝗇𝑁:𝑌!𝜏′
TR-Box
𝜏≤𝜏ΓΓ−𝜏⊢𝑉:[𝜏]𝑋Γ,𝑥:𝑋⊢𝑁:𝑌!𝜏′
Γ⊢𝗎𝗇𝖻𝗈𝗑[𝜏]𝑉𝖺𝗌𝑥𝗂𝗇𝑁:𝑌!𝜏′
TR-Unbox
Here 𝜏Γ sums the time markers in Γ, and Γ−𝜏 moves back through that accumulated time. Thus TR-Unbox checks both that enough time has elapsed and that the boxed value was already in scope at the earlier point.
A machine state stores elapsed-time markers and bindings 𝑥↦[𝜏]𝑋𝑉. Its three temporal steps are ⟨𝑆∣𝖽𝖾𝗅𝖺𝗒𝜏𝑀⟩⟼𝗍𝗋⟨𝑆,⟨𝜏⟩∣𝑀⟩,⟨𝑆∣𝖻𝗈𝗑[𝜏]𝑉𝖺𝗌𝑥𝗂𝗇𝑁⟩⟼𝗍𝗋⟨𝑆,𝑥↦[𝜏]𝑋𝑉∣𝑁⟩,⟨𝑆∣𝗎𝗇𝖻𝗈𝗑[𝜏]𝑦𝖺𝗌𝑥𝗂𝗇𝑁⟩⟼𝗍𝗋⟨𝑆∣𝑁[𝑆(𝑦)/𝑥]⟩(𝑦∈𝑆). If Γ𝑆 is the context represented by 𝑆, the paper proves:
if ⊢𝑆 and Γ𝑆⊢𝑀:𝑋!𝜏, then 𝑀 is a return or unhandled-operation result, or the machine steps (Theorem 3.7);
if that state steps to ⟨𝑆′∣𝑀′⟩, then ⊢𝑆′ and some 𝜏′ satisfies 𝜏𝑆+𝜏=𝜏𝑆′+𝜏′ and Γ𝑆′⊢𝑀′:𝑋!𝜏′ (Theorem 3.10);
translating states to temporal computation contexts 𝐾𝑆 makes each step equationally sound: 𝐾𝑆[𝑀]≡𝐾𝑆′[𝑀′]:𝑋!(𝜏𝑆+𝜏) (Corollary 4.10).
The accompanying Agda development contains the syntax, renaming, substitution, progress, preservation, and equational theory. The authors explicitly report that the proof of Theorem 4.9, from which the corollary is obtained, was not yet formalized. The paper proof and the partial formalization must therefore remain separate evidence.
Likewise, the 𝖥𝗅𝗈𝗐𝐴=𝖲𝗍𝗋(𝖬𝖺𝗒𝖻𝖾𝐴) construction above is a Simply RaTT library encoding, not a primitive clock-indexed flow type. A refinement such as 𝖥𝗅𝗈𝗐𝑐𝐴, with a proposed masking rule Γ⊢𝑑:𝖢𝗅𝗈𝖼𝗄𝑑Γ⊢𝑓:𝖥𝗅𝗈𝗐𝑐𝐴Γ⊢𝗐𝗁𝖾𝗇𝑑𝑓:𝖥𝗅𝗈𝗐𝑐∧𝑑𝐴, is a conjectural extension here. Before it can inherit productivity or the old-heap result, it needs clock subtyping, operational semantics, a clock-indexed logical relation, and a proof that masking preserves reachable roots. No such theorem is imported by the displayed rule. The parallel claim that arbitrary 𝜆[𝜏] state can be added to Simply RaTT without implicit leaks is also a conjecture: the two state models require an explicit translation and invariant-preservation proof.
Sources and theorem boundary
The typing rules are Figure 4, the machine is Sections 3–4, productivity and causality are Theorems 3.1–3.2, and the Fundamental Property is Theorem 6.3 of Bahr, Graulund, and Møgelberg [BGM19]. The local Coq archive is pinned to the authors’ repository commit recorded in the reference package; archive integrity is not a claim of replay under current Rocq. Jeffrey supplies the LTL precursor comparison [Jef12]. Simply RaTT’s switch, scan, and Lustre-flow encodings are in Sections 4–5 of that paper. The temporal-resource typing rules are Figure 3, its machine is Figure 4, and its exact results are Theorems 3.7, 3.10, 4.9 and Corollary 4.10 of Ahman and Žajdela [A Z24]. Nakano’s modality is cited only as the guarded-recursion precursor [Nak00]. This chapter proves neither a generic progress and preservation package for every temporal calculus nor a bound on deliberate growth of stable application data.
★★☆Space audit. Compare a stable natural accumulator with a stable list accumulator. State which memory is discarded by the machine and which memory is retained explicitly.
★★★Practical project.simply-ratt-stream-checker The implemented algorithm is a finite running-sum transducer paired with a root-count model. Preserve two invariants: output 𝑖 depends only on inputs through 𝑖, and the bounded model retains exactly one temporal root after each step. Run artifacts/ch55-simply-ratt-stream/corpus.kp; on the named input (2,11,5), require (2,13,18), current-input dependence, root counts (1,1,1), and detection of the history counts (1,2,3). Acceptance is the four named PASS lines and empty audit in appendix E. Then add a causal two-state transducer and its expected trace. Finally replace the bounded-root function by the history-retaining one and require the unchanged root-bound oracle to reject the mutant.