Basically, what I am trying to do is have a generic simulator-interface which acts as the lose coupling between the model and the user interface, which acts as the view. My simulator interface looks like this:
type ISimulator<'Collection, 'Item, 'Value> =
inherit System.IObservable<'Collection>
inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
abstract Start: unit -> unit
abstract Stop: unit -> unit
abstract Reset: unit -> unit
abstract Reset: 'Collection -> unit
abstract Advance: int<gen> -> unit
abstract InitialState: 'Collection
with get
abstract CurrentState: 'Collection
with get
abstract Rule: ('Item -> 'Value)
with get, set
abstract Generation: int<gen>
with get, set
abstract Speed: float<gen/sec>
with get, set
abstract Running: bool
with get
‘Collections is the type of a data collection, ‘Item is the type of a single data item, and ‘Value is the type of its actual value (for example <Matrix, Cell, float>, <Tree, Node, string> etc.). Now, the line
inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
produces an error:
This type implements or inherits the same interface at different generic instantiations 'System.IObservable<Interface.ISimulator<'Collection,'Item,'Value>>' and 'System.IObservable<'Collection>'. This is not permitted in this version of F#.
Effectively, I want this interface to say that both the Collection which serves as the data the simulation is running upon and the Simulator itself to be observable separately. In the end, I want a part of my user interface to display the current data (for example a matrix) and a different part to display and control the simulator, with some buttons like “run”, “stop”, “reset” etc. Since the simulator might also be stopped by other means than just clicking a button (for example, after reaching some specific state, generation etc.), that control needs updates from the simulator, too, but not on the state of the data, but the simulator itself.
It is not possible to make the collection interface I would write observable, as that collection wouldn’t be modified during simulation, but transformed by applying a function, and the transformation would produce a new collection, which the simulator then stores (and notifies the observers of the collection).
What shall I do?
- Break the immutability concept and
always keep the same collection (in
terms of identity, not contained
values) which just changes over time
instead of producing new, modified
collections? - Break lose coupling and have my user
interface know the exact
implementation which would, outside
of the interface, provide a second
means to observer the simulator
itself? Have all user interface
components which require updates from
the simulator observe the whole
thing, not just the relevant data? - Create a seperate interface to
observe the collection, and have my
simulator implementation implement
both interfaces? - Something else?
Have you considered exposing the observables through properties, sort of like traditional events?
This allows consumers to be explicit about which behavior they’re observing.