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
Related
I need to be able to identify the source of an unsigned extrinsic for spam prevention purposes. Assume there is a set of known authorities from whom I am willing to accept an unsigned extrinsic. I want to check that the sender of the unsigned extrinsic is a member of this authority set (and that they are who they say they are).
From what I can tell there are a couple of different approaches and I would like to better understand the differences between each and the trade-offs involved.
Add a signature as a call parameter and define ValidateUnsigned.
This approach is used in the ImOnline pallet. Roughly speaking:
decl_module!(
// ...
fn my_unsigned_call(_origin,
args: MyArgs<T>,
authority: T::Authority,
signature: T::Signature) {
// Handle the call
todo!()
}
)
impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
// ...
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
) -> TransactionValidity {
if let Call::my_unsigned_call(args, authority, signature) = call {
// Check the sender is in the approved authority set and verify sig
todo!();
}
}
}
Implement SignedExtension for some metadata associated with the pallet trait. This is touched upon in the docs and seems to be implemented in the TransactionPayment pallet. Implementation would be something like this:
struct SenderInfo<T> {
authority: T::Authority,
signature: T::Signature,
}
impl<T: Config + Send + Sync> SignedExtension for SenderInfo<T>
where
<T as frame_system::Config>::Call: IsSubType<Call<T>>,
{
// ...
fn validate_unsigned(
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize
) -> TransactionValidity {
// validate self.authority and self.signature
}
}
This SignedExtension then needs to be aggregated into the SignedExtra of the runtime. (Right?)
I am tending towards using the second option since it seems cleaner: it doesn't require me to pollute my method signatures with extra information that is not even used in the method call. But would this mean that any transaction submitted to the runtime, signed or unsigned, would need to add this customised SignedExtra?
Are there any other considerations I should be aware of?
I'm working on a very similar thing.
I was able to do so with your approach 1.
Basically I do check two things there:
If payload was signed properly - When you think about it, this will tell you only about the user, but it doesn't check if a user is your authority user.
I do check if this account is on my authorities list
My working example is available here https://github.com/korzewski/jackblock/blob/master/pallets/jackblock/src/lib.rs#L401
Although, this is not perfect because I need to keep a second list of Authorities and add them manually.
Currently I'm trying to refactor it, so my authorities accounts are the same as my validators (Aura pallet). Still looking for a solution so maybe you know how to solve it? Basically how to reuse Aura pallet in my own pallet
Here's two F# scenarios. I have an abstract class:
type IAbstractObj =
abstract DoSomething : bool -> bool
Scenario 1:
I implement the interface into a type:
type ConcreteObj =
interface IAbstractObj with
member this.DoSomething bool = true
This is then used in the application by instantiation:
let foo = new ConcreteObj();
Scenario 2:
I bind an instance of the type with a let binding and use it as a 'free function holder':
let ConcreteObj = {
new IAbstractObj with
member this.DoSomething bool = true
}
And use it as such:
let foo = ConcreteObj
What are the differences between these usages? In either case, the types don't need to hold any additional runtime state.
Would there be a performance difference (miniscule)? With modules containing 'let' bindings, is memory only allocated to the bindings that are actually evaluated in other parts of the application?
Would scenario 1 allocate a small amount of memory to hold a pointer to the instance (even though it is stateless)?
It's fairly important for my application. I use many interfaces for validators and serializers that dont hold any instance state. With my C# background, I'm used to just having to create an instance of a class that inherits an interface even if it has a paramaterless constructor and is clearly only a holder of essentially static functions.
There is a more idiomatic option than either of those. Instead of creating a new type for each option, simply create a record type which has two members which are functions. You nearly defined it yourself in the comments:
type serializer<'a, 'b> =
{ Serialize : 'a -> 'a Option
Deserialize: 'b -> 'b Option}
let concrete = { Serialize = (fun (x)->Some(x)); Deserialize = (fun (x)->Some(x)) }
So whatever is consuming this should take a serializer.
The principal difference between the two is that an object expression has the static type of the interface or abstract class it implements. Whereas, class-based interface implementation is explicit and requires casting to access interface members.
For trivial interface implementations, an object expression is generally a better choice than a class.
(FWIW, I think your performance concerns are inconsequential.)
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.
Sorry if this is basic but I was trying to pick up on .Net 3.5.
Question: Is there anything great about Func<> and it's 5 overloads? From the looks of it, I can still create a similar delgate on my own say, MyFunc<> with the exact 5 overloads and even more.
eg: public delegate TResult MyFunc<TResult>() and a combo of various overloads...
The thought came up as I was trying to understand Func<> delegates and hit upon the following scenario:
Func<int,int> myDelegate = (y) => IsComposite(10);
This implies a delegate with one parameter of type int and a return type of type int. There are five variations (if you look at the overloads through intellisense). So I am guessing that we can have a delegate with no return type?
So am I justified in saying that Func<> is nothing great and just an example in the .Net framework that we can use and if needed, create custom "func<>" delegates to suit our own needs?
Thanks,
The greatness lies in establishing shared language for better communication.
Instead of defining your own delegate types for the same thing (delegate explosion), use the ones provided by the framework. Anyone reading your code instantly grasps what you are trying to accomplish.. minimizes the time to 'what is this piece of code actually doing?'
So as soon as I see a
Action = some method that just does something and returns no output
Comparison = some method that compares two objects of the same type and returns an int to indicate order
Converter = transforms Obj A into equivalent Obj B
EventHandler = response/handler to an event raised by some object given some input in the form of an event argument
Func = some method that takes some parameters, computes something and returns a result
Predicate = evaluate input object against some criteria and return pass/fail status as bool
I don't have to dig deeper than that unless it is my immediate area of concern. So if you feel the delegate you need fits one of these needs, use them before rolling your own.
Disclaimer: Personally I like this move by the language designers.
Counter-argument : Sometimes defining your delegate may help communicate intent better. e.g. System.Threading.ThreadStart over System.Action. So it’s a judgment call in the end.
The Func family of delegates (and their return-type-less cousins, Action) are not any greater than anything else you'd find in the .NET framework. They're just there for re-use so you don't have to redefine them. They have type parameters to keep things generic. E.g., a Func<T0,bool> is the same as a System.Predicate<T> delegate. They were originally designed for LINQ.
You should be able to just use the built-in Func delegate for any value-returning method that accepts up to 4 arguments instead of defining your own delegate for such a purpose unless you want the name to reflect your intention, which is cool.
Cases where you would absolutely need to define your delegate types include methods that accept more than 4 arguments, methods with out, ref, or params parameters, or recursive method signatures (e.g., delegate Foo Foo(Foo f)).
In addition to Marxidad's correct answer:
It's worth being aware of Func's related family, the Action delegates. Again, these are types overloaded by the number of type parameters, but declared to return void.
If you want to use Func/Action in a .NET 2.0 project but with a simple route to upgrading later on, you can cut and paste the declarations from my version comparison page. If you declare them in the System namespace then you'll be able to upgrade just by removing the declarations later - but then you won't be able to (easily) build the same code in .NET 3.5 without removing the declarations.
Decoupling dependencies and unholy tie-ups is one singular thing that makes it great. Everything else one can debate and claim to be doable in some home-grown way.
I've been refactoring slightly more complex system with an old and heavy lib and got blocked on not being able to break compile time dependency - because of the named delegate lurking on "the other side". All assembly loading and reflection didn't help - compiler would refuse to just cast a delegate() {...} to object and whatever you do to pacify it would fail on the other side.
Delegate type comparison which is structural at compile time turns nominal after that (loading, invoking). That may seem OK while you are thinking in terms of "my darling lib is going to be used forever and by everyone" but it doesn't scale to even slightly more complex systems. Fun<> templates bring a degree of structural equivalence back into the world of nominal typing . That's the aspect you can't achieve by rolling out your own.
Example - converting:
class Session (
public delegate string CleanBody(); // tying you up and you don't see it :-)
public static void Execute(string name, string q, CleanBody body) ...
to:
public static void Execute(string name, string q, Func<string> body)
Allows completely independent code to do reflection invocation like:
Type type = Type.GetType("Bla.Session, FooSessionDll", true);
MethodInfo methodInfo = type.GetMethod("Execute");
Func<string> d = delegate() { .....} // see Ma - no tie-ups :-)
Object [] params = { "foo", "bar", d};
methodInfo.Invoke("Trial Execution :-)", params);
Existing code doesn't notice the difference, new code doesn't get dependence - peace on Earth :-)
One thing I like about delegates is that they let me declare methods within methods like so, this is handy when you want to reuse a piece of code but you only need it within that method. Since the purpose here is to limit the scope as much as possible Func<> comes in handy.
For example:
string FormatName(string pFirstName, string pLastName) {
Func<string, string> MakeFirstUpper = (pText) => {
return pText.Substring(0,1).ToUpper() + pText.Substring(1);
};
return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}
It's even easier and more handy when you can use inference, which you can if you create a helper function like so:
Func<T, TReturn> Lambda<T, TReturn>(Func<T, TReturn> pFunc) {
return pFunc;
}
Now I can rewrite my function without the Func<>:
string FormatName(string pFirstName, string pLastName) {
var MakeFirstUpper = Lambda((string pText) => {
return pText.Substring(0,1).ToUpper() + pText.Substring(1);
});
return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}
Here's the code to test the method:
Console.WriteLine(FormatName("luis", "perez"));
Though it is an old thread I had to add that func<> and action<> also help us use covariance and contra variance.
http://msdn.microsoft.com/en-us/library/dd465122.aspx