using System; namespace imm; public record class Context : imm.Recorded { } public record class State : imm.Recorded> where T : State where CTX : Context { virtual public (CTX, T) onEnter(CTX ctx, State oldState) { return (ctx, (T)this); } virtual public (CTX, T) onExit(CTX ctx, State newState) { return (ctx, (T)this); } } public record class FSM : imm.Recorded> where T : FSM where CTX : Context where ST : State { public CTX Context { get; private set; } public ST State { get; private set; } public FSM(CTX context, ST state) { Context = context; State = state; } public FSM Transition(ST newState) { var (newOldCTX, oldState) = State.onExit(Context, newState); var (newCTX, storeState) = newState.onEnter(newOldCTX, oldState); return this with { Context = newCTX, State = storeState, }; } }