Last active
April 29, 2025 16:02
-
-
Save idugalic/bc7b9c42e170689aa8e21afbdfbf28af to your computer and use it in GitHub Desktop.
Information Systems
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.fraktalio | |
// ################################################## | |
// ################################################## | |
// Information System - encoded in Kotlin type system | |
// ################################################## | |
// ################################################## | |
/** | |
* A formalization of the traditional/state stored information system. | |
* State-Stored systems are traditional systems that are only storing the current state by overwriting the previous state in the storage. | |
* A function that takes command/request and `current` state of the system to produce `new` state of the system as a result. | |
* | |
* @param Command an intent to change the state of the system | |
* @param State a state of the system | |
*/ | |
typealias StateStoredSystem<Command, State> = (Command, State) -> State | |
/** | |
* A formalization of the event-sourced information system. | |
* Event-Sourced systems are storing the events in immutable storage by only appending. | |
* A function that takes command/request and `current` state (sequence of Events) of the system to produce `new` state (sequence of Events) of the system as a result. | |
* | |
* @param Command an intent to change the state of the system | |
* @param Event a state change itself | |
*/ | |
typealias EventSourcedSystem<Command, Event> = (Command, Sequence<Event>) -> Sequence<Event> | |
/** | |
* A formalization of any information system. | |
* This encoding captures both event-sourced and state-stored systems, providing a unified model for different architectural styles. | |
*/ | |
typealias System<Command, State, Event> = Triple< | |
(Command, State) -> Sequence<Event>, // 1. decide | |
(State, Event) -> State, // 2. evolve | |
() -> State // 3. initial state | |
> | |
/** | |
* Mapping general system into traditional/state-stored system | |
*/ | |
fun <Command, State, Event> System<Command, State, Event>.asStateStoredSystem(): StateStoredSystem<Command, State> = | |
{ command, state -> | |
first(command, state).fold<Event, State>(third()) { state, event -> second(state, event) } | |
} | |
/** | |
* Mapping general system into event-sourced system | |
*/ | |
fun <Command, State, Event> System<Command, State, Event>.asEventSourcedSystem(): EventSourcedSystem<Command, Event> = | |
{ command, events -> | |
first(command, events.fold<Event, State>(third()) { state, event -> second(state, event) }) | |
} | |
// ###################### | |
// Functors of the System | |
// ###################### | |
// These functors provide several key benefits: | |
// - Type Safety: Transformations are checked at compile-time, reducing runtime errors. | |
// - Composability: Systems can be transformed and composed without breaking their internal structure. | |
// - Flexibility: Easy adaptation of existing systems to work with new types or requirements. | |
// ###################### | |
// Map system that can handle command(s) of type `Command` into a system that can handle command(s) of type `Command2` | |
inline fun <Command, Command2, State, Event> System<Command, State, Event>.mapCommand(crossinline f: (Command2) -> Command): System<Command2, State, Event> = | |
Triple( | |
{ command2, state -> first(f(command2), state) }, // Transform Command2 to Command using f() in decide function | |
second, // Keep evolve function as is | |
third // Keep initial state as is | |
) | |
// Map system that can publish event(s) of type `Event` into a system that can publish event(s) of type `Event2` | |
inline fun <Command, State, Event, Event2> System<Command, State, Event>.mapEvent( | |
crossinline fl: (Event2) -> Event, | |
crossinline fr: (Event) -> Event2 | |
): System<Command, State, Event2> = | |
Triple( | |
{ command, state -> first(command, state).map { fr(it) } }, | |
{ state, event2 -> second(state, fl(event2)) }, | |
third | |
) | |
// Map system that can manage state(s) of type `State` into a system that can manage state(s) of type `State2` | |
inline fun <Command, State, State2, Event> System<Command, State, Event>.mapState( | |
crossinline fl: (State2) -> State, | |
crossinline fr: (State) -> State2 | |
): System<Command, State2, Event> = | |
Triple( | |
{ command, state2 -> first(command, fl(state2)) }, | |
{ state2, event -> fr(second(fl(state2), event)) }, | |
{ fr(third()) } | |
) | |
fun main() { | |
println("https://fraktalio.com/fmodel/") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is lovely! ❤️