using System; namespace fsm; 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, }; } }