I'm looking for the best way to propagate model updates to the GUI, using a "classic" (as in: non reactive functional) GUI toolkit: Terminal.GUI. Currently I have this code (simplified):
type Tui(state: StateManager) =
let state = state
let window = Window(bla bla bla)
let lblPath = Label(bla bla bla)
let lstView =
{ new ListView(bla bla bla) with
member this.ProcessKey(k: KeyEvent) =
let updateViews() =
Application.MainLoop.Invoke(fun () ->
this.SetSource model.CurrentState.LstData
lblPath.Text <- ustr model.CurrentState.CurrPath)
match k.Key with
| Key.CursorRight ->
state.changeTheState()
updateViews()
true
| _ -> true }
do
Application.Init()
// add all GUI components: window.add(lblPath), etc
Application.Run()
// XXX repetition of updateViews() above!
Application.MainLoop.Invoke(fun () ->
lstView.SetSource model.CurrentState.LstData
lblPath.Text <- ustr model.CurrentState.CurrPath)
The issue here is that the code to update the view components is duplicated. I believe this is because:
in that ProcessKey method of the ListView object expression I cannot access any external method of the Tui class (this is probably also because F# compiler is one-pass only (?))
outside that method I cannot access the updateView function
Is there a better way of doing this that would avoid code repetition? Am I using the wrong pattern GUI update pattern?
(Complete code is here)
Of course, it doesn't need to be too complicated - refactor your update to just take in a listview parameter:
let updateViews (lstView: ListView) =
Application.MainLoop.Invoke(fun () ->
lstView.SetSource state.CurrentState.LstData
...
)
And inside the member definition, call:
updateViews(this)
And below, you can use updateViews lstView.
When you use an object expression, the type of the expression becomes the type you specify in new <type>, so any type augmentations you do inside won't make it outside. For a more OOP approach, declare an intermediate type:
[<AbstractClass>]
type UpdateableList() =
inherit ListView([||])
abstract member Update: unit -> unit
implement your update logic:
{ new UpdateableList(X = Pos.At(0), Y = Pos.At(2), ...) with
member this.Update() =
...
and in your setup, you have access to a public method:
lstView.Update()
Related
I have a fairly simple javascript method
(props,propName,componentName) => {
var value = props[propName];
const getOrSpread = name =>
props[name] || props.spread && props.spread[name];
// remainder of function code omitted
}
that is working in javascript land. I'm trying to convert it to fable but either I can get it to have a definitely exists property access to .spread or dynamic access to props[propName] but not both
module JsxHelpers =
type IReactProps =
abstract member spread : obj
let isfuncOrNullPropType (props:IReactProps) (propName:string) componentName =
let propsO :obj = box props
let value:obj = propsO?propName
let valueAttempt2:obj = (box props)?(propName)
// rest of translation not attempted yet
value
where if props is defined as IReactProps, then .spread works, but neither of the two possible let value lines compile.
or props is defined as obj and it says `This expression was expected to have type 'obj' but here has type ''a -> obj'
even the simplest object from the documentation doesn't appear to compile:
let isfuncOrNullPropType (props:obj) (propName:string) =
let value2:obj = props?propName
value2
using "fable-core": "^1.0.0-narumi-905"
You definitely need to put the prop name in parentheses according to the documentation. The compiler error you're getting is because props?(propName) returns type 'a -> obj. Apparently, the dynamic (?) operator returns an Applicable, and from the fable source:
/// DO NOT USE: Internal type for Fable dynamic operations
type Applicable = obj->obj
Perhaps try:
let value : obj = unbox<obj> (props?(propName))
I'm trying to create a solution that has a lower-level library that will know that it needs to save and load data when certain commands are called, but the implementation of the save and load functions will be provided in a platform-specific project which references the lower-level library.
I have some models, such as:
type User = { UserID: UserID
Situations: SituationID list }
type Situation = { SituationID: SituationID }
And what I want to do is be able to define and call functions such as:
do saveUser ()
let user = loadUser (UserID 57)
Is there any way to define this cleanly in the functional idiom, preferably while avoiding mutable state (which shouldn't be necessary anyway)?
One way to do it might look something like this:
type IStorage = {
saveUser: User->unit;
loadUser: UserID->User }
module Storage =
// initialize save/load functions to "not yet implemented"
let mutable storage = {
saveUser = failwith "nyi";
loadUser = failwith "nyi" }
// ....elsewhere:
do Storage.storage = { a real implementation of IStorage }
do Storage.storage.saveUser ()
let user = Storage.storage.loadUser (UserID 57)
And there are variations on this, but all the ones I can think of involve some kind of uninitialized state. (In Xamarin, there's also DependencyService, but that is itself a dependency I would like to avoid.)
Is there any way to write code that calls a storage function, which hasn't been implemented yet, and then implement it, WITHOUT using mutable state?
(Note: this question is not about storage itself -- that's just the example I'm using. It's about how to inject functions without using unnecessary mutable state.)
Other answers here will perhaps educate you on how to implement the IO monad in F#, which is certainly an option. In F#, though, I'd often just compose functions with other functions. You don't have to define an 'interface' or any particular type in order to do this.
Develop your system from the Outside-In, and define your high-level functions by focusing on the behaviour they need to implement. Make them higher-order functions by passing in dependencies as arguments.
Need to query a data store? Pass in a loadUser argument. Need to save the user? Pass in a saveUser argument:
let myHighLevelFunction loadUser saveUser (userId) =
let user = loadUser (UserId userId)
match user with
| Some u ->
let u' = doSomethingInterestingWith u
saveUser u'
| None -> ()
The loadUser argument is inferred to be of type User -> User option, and saveUser as User -> unit, because doSomethingInterestingWith is a function of type User -> User.
You can now 'implement' loadUser and saveUser by writing functions that call into the lower-level library.
The typical reaction I get to this approach is: That'll require me to pass in too many arguments to my function!
Indeed, if that happens, consider if that isn't a smell that the function is attempting to do too much.
Since the Dependency Inversion Principle is mentioned in the title of this question, I'd like to point out that the SOLID principles work best if all of them are applied in concert. The Interface Segregation Principle says that interfaces should be as small as possible, and you don't get them smaller than when each 'interface' is a single function.
For a more detailed article describing this technique, you can read my Type-Driven Development article.
You can abstract storage behind interface IStorage. I think that was your intention.
type IStorage =
abstract member LoadUser : UserID -> User
abstract member SaveUser : User -> unit
module Storage =
let noStorage =
{ new IStorage with
member x.LoadUser _ -> failwith "not implemented"
member x.SaveUser _ -> failwith "not implemented"
}
In another part of your program you can have multiple storage implementations.
type MyStorage() =
interface IStorage with
member x.LoadUser uid -> ...
member x.SaveUser u -> ...
And after you have all your types defined you can decide which to use.
let storageSystem =
if today.IsShinyDay
then MyStorage() :> IStorage
else Storage.noStorage
let user = storageSystem.LoadUser userID
I'm trying to compile the source code from : Custom WPF Controls in F#
How ever this line :
let (handler, event) = Event.create<EventArgs>()
raises an error :
The value, constructor, namespace or type 'create' is not defined
The MSDN's Control.Event Module (F#) page does speak about such a function :
The additional functionality provided by the Event module is
illustrated here. The following code example illustrates the basic use
of Event.create to create an event and a trigger method, add two
event handlers in the form of lambda expressions, and then trigger the
event to execute both lambda expressions.
type MyType() =
let myEvent = new Event<_>()
member this.AddHandlers() =
Event.add (fun string1 -> printfn "%s" string1) myEvent.Publish
Event.add (fun string1 -> printfn "Given a value: %s" string1) myEvent.Publish
member this.Trigger(message) =
myEvent.Trigger(message)
let myMyType = MyType()
myMyType.AddHandlers()
myMyType.Trigger("Event occurred.")
However note that it's only mentionned in the description, not in the example.
Also, the Control.Event Module (F#) page has no reference to such a create function.
I guess it might be an old function or something, but I'm new to F# so I can't see what it should be replaced with..
Event.create is a fairly old API for events, from before F# 2.0 judging by what's on MSDN. It gave you a trigger function and a published event - both of which now live as Publish and Trigger members of Event class.
So if you wanted to implement create in the 'modern' terms, it might look somewhat like this:
module Event =
let create<'T> () =
let event = Event<'T>()
event.Trigger, event.Publish
I don't suggest you use it universally, but perhaps that's good enough to bring that old code back to life (the correct approach here being refactoring it to use Publish and Trigger instead of create).
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?
type ISimulator<'Collection, 'Item, 'Value> =
abstract Items: System.IObservable<'Collection>
abstract Control: System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
abstract Start: unit -> unit
...
This allows consumers to be explicit about which behavior they're observing.
Here we go, I made this bare-bones implementation of IObservable, of which I then expose public properties according to the interface definition dahlbyk provided. I've found the basic idea for this implementation on this website and generalized a bit from there:
open System
type Observable<'a>() =
let mutable _observers: List<IObserver<'a>> = []
let Notify func =
_observers
|> Seq.map(fun (observer: IObserver<'a>) -> async { return func observer} )
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
interface IObservable<'a> with
member this.Subscribe (observer: IObserver<'a>) =
_observers <- observer :: _observers
{ new IDisposable with
member this.Dispose() =
_observers <- _observers |> List.filter((<>) observer) }
member this.Next value =
Notify(fun (observer: IObserver<'a>) -> observer.OnNext value)
member this.Error error =
Notify(fun (observer: IObserver<'a>) -> observer.OnError error)
member this.Completed() =
Notify(fun (observer: IObserver<'a>) -> observer.OnCompleted)
The class containing instances of this implementation as properties just treats it as an Observable<'a> object, while to everyone else it is exposed only as an IObservable<'a> interface. I think this is nice in terms of loose coupling and still allows very straightforward usage on either end of the Observer/Observable pair.
P.S.: This is also why I love F# - this entire construct would be a total mess to implement in a language like C++; but here I can just pass a function into another function in order to apply it on all observers. :)
I have a non-disposable class with Open/Close syntax that I'd like to be able to use, so I'm trying to inherit from it, and work the Open into the new and the Close into Dispose.
The second part is ok, but I can't work out how to do the Open:
type DisposableOpenCloseClass(openargs) =
inherit OpenCloseClass()
//do this.Open(openargs) <-- compiler no like
interface IDisposable
with member this.Dispose() = this.Close()
(cf. this question which I asked a long time ago, but I can't join the dots to this one)
Key is as this:
type OpenCloseClass() =
member this.Open(x) = printfn "opened %d" x
member this.Close() = printfn "closed"
open System
type DisposableOpenCloseClass(openargs) as this =
inherit OpenCloseClass()
do this.Open(openargs)
interface IDisposable
with member this.Dispose() = this.Close()
let f() =
use docc = new DisposableOpenCloseClass(42)
printfn "inside"
f()
As Brian suggests, you can use the as this clause. However, in F#, it is usually recomended to use subclassing (inheritance) only when there is a really good reason for that (e.g. you need to implement some virtual class and pass it to a .NET library).
If I was implementing your example, I would probably prefer function returning IDisposable using a simple object expression:
let disposableOpenClose(openargs) =
let oc = new OpenCloseClass()
oc.Open(openargs)
{ new IDisposable with
member this.Dispose() = oc.Close() }
let f() =
use docc = disposableOpenClose(42)
printfn "inside"
To some point, this is just a personal preference, but I think it is a preferred option, because it is simpler than using inheritance (although I don't have any document to link here :-)). Also, the compiled code may be a bit simpler, because handling as this may require some runtime checks.