F# how to AddHandler alike VB.NET - f#

VB.NET code is :
AddHandler TheGrp.DataChanged, AddressOf theGrp_DataChange
So how can I do same with F# ?
theGrp.DataChanged.AddHandler(X.theGrp_DataChange)
Error 1 This function takes too many arguments, or is used in a context where a function is not expected

Try theGrp.DataChanged.AddHandler(fun o e -> X.theGrp_DataChange(o, e)). The signature for AddHandler indicates that it takes a delegate, so you can either explicitly create one (via something like DataChangedEventHandler(fun o e -> X.theGrp_DataChange(o, e))) or you can let the compiler implicitly add the delegate constructor when given a function definition, but you can't just use the method itself.

Alternatively, if you don't want to create a lambda expression explicitly, you can also write (In this case, the function signature matches the signature required by the delegate, so it should work):
theGrp.DataChanged.AddHandler(DataChangedEventHandler(x.theGrp_DataChanged))
Also, if you don't need the sender argument, you can declare the theGrp_DataChanged method to take only the event args argument and then write just:
theGrp.DataChanged.Add(x.theGrp_DataChanged)

Related

Action Delegates in F#

In the Giraffe library examples, I noticed the following:
[<EntryPoint>]
let main _ =
WebHostBuilder()
.UseKestrel()
.Configure(Action<IApplicationBuilder> configureApp)
.ConfigureServices(configureServices)
.Build()
.Run()
0
While I understand most of it, I'm unclear with Configure(Action<IApplicationBuilder> configureApp) - is configureApp being cast to an Action<IApplicationBuilder>?
UPDATE
As I understand constructor calls, per Microsoft documentation:
You initialize your objects together with constructor arguments,
either by listing the arguments in order and separated by commas and
enclosed in parentheses, or by using named arguments and values in
parentheses.
It is creating a new delegate, using the delegate constructor like an F# function. The C# equivalent would be:
.Configure(new Action<IApplicationBuilder>(configureApp))

Are instance methods closures?

In the book, "Swift Programming Language 3.0", it mentioned that types of closure include:
Global functions are closures that have a name and do not capture
any values
Nested function are closures that have a name and can
capture values from their enclosing function
Closure expression are
unnamed closure written in a lightweight syntax that can capture
values from their surrounding context
I was just wondering does a function that exist in class scope count as a closure? One can certainly pass around such function as an argument to other function, but is it a closure?
Yes! Absolutely! Here's an example that uses the lowercased() method of String.
let aClosure: (String) -> () -> String = String.lowercased
let anUpperCasedString = "A B C"
print(anUpperCasedString)
let aLowerCaseString = aClosure(anUpperCasedString)()
print(aLowerCaseString)
You can see that the type of this closure is (String) -> () -> String. This is because String.lowercased is completely unapplied, it has no clue what instance it's operating on.
Calling aClosure(anUpperCasedString) will return a closure that's now () -> String. Baked into it is the instance it'll operate on. Only when you call this new closure with no params (()), will it actually execute the body of lowercased(), operating on the instance you gave it in the previous step, and return you the String result.
As a consequence, this is also valid:
let aLowerCaseString = String.lowercased("QWERTY")()
It just does all the steps above in one inlined step.
This technique is called function currying. This post talks more about this technique (called function currying) as it applies to instance methods in Swift.

f# function not recognized as parameter

Please unwrap these type signatures to help me understand why this doesn't work.
Then, if you have a solution, that would be great too.
I have this code and the agent.Post command has the signature Observer.Create<'T>(onNext: Action<'T>) : IObserver<'T>
let reservatinoRequestObserver = Observer.Create agent.Post
interface IHttpControllerActivator with
To my knowledge, this means that Observer.Create should take an Action with a single generic parameter and then return an IObserver.
Now the definition of Post is member MailboxProcessor.Post : message:'Msg ->unit
So... Post is a method, no? It is a method that takes a single parameter no? And it returns void no? So shouldn't it be a candidate for Observer.Create? Isn't that the exact specification of Action<'T>?
Well, somethings up, I get This function takes too many arguments, or is used in a context where a function is not expected:
Help me out... I freely admit I suck at F#
First, agent.Post returns unit, which is a different thing from void. F# will usually convert back and forth between void and unit for you, but they are not the same thing.
Second, F# functions do not implicitly convert to .NET delegates.
But there are some ways to do it:
You can explicitly create the delegate using its constructor:
let o = Observer.Create (new Action<_>( agent.Post ))
Lambdas are nicely wrapped too
let o = Observer.Create (fun msg -> agent.Post msg)
Use F# Rx-wrappers
Also there are a couple of F# wrappers/interop for Rx on nuget - just have a look, I think any will do

Why does io\open not work in moonscript?

Moonscript uses \ to call methods so can someone explain to me why the code below does not work:
> file = io\open("mix.exs", "rb")
[string "tmp"]:1: calling 'open' on bad self (string expected, got table)
but when you call it to read the file it does ?
> file\read!
"Code.ensure_loaded?(Hex) and Hex.start
The io.open function expects to get a string as the first argument but io\open (like io:open in lua itself) is actually passing the io table as the first argument. That is it is a method call.
io\open("file", "mode")/io:open("file", "mode") are syntactic sugar for io.open(io, "file", "mode").
This is why file\read! works without an explicit argument because file gets passed as the first argument to the read("file", "format") function.
Moonscript uses \ to call methods
to call member methods. as in a\b c, ... translates to a.b(a,c,...).
this doesn't work here because io.open is a static function (io.open(what,how)), not a member (io.open(self,what,how)).
you couldn't call io:open in Lua either. the only place where io functions allow for being called as members is when you want to read/write stdio.
but when you call it to read the file it does ?
because now it's a member method of the file. you're actually still using io.read there, but the file object has io as a metatable index, therefore allowing you to access the same function via file.read, and since file\read! translates to file.read(file) it's the same thing.
so essentially the answer boils down to "because io:open doesn't work in Lua".

Why can't a function with byref be converted directly to delegate?

Under normal circumstances, F# functions can be converted to delegates by calling new DelegateType and passing in the function as an argument. But when the delegate contains byref parameter, this is not possible directly. For example the code:
type ActionByRef<'a> = delegate of 'a byref -> unit
let f (x:double byref) =
x <- 6.0
let x = ref 42.0
let d = new ActionByRef<_>(f)
won't compile, giving the following error:
This function value is being used to construct a delegate type whose signature includes a byref argument. You must use an explicit lambda expression taking 1 arguments.
Following the error, modifying the code to use
let d = new ActionByRef<_>(fun x -> f(&x))
works. But my question is: why is this necessary? Why won't F# allow the conversion from named function to this delegate, but conversion from lambda is fine?
I came upon this behavior when researching another question. I realize byref is meant only for compatibility with other .Net languages.
I think the problem is that byref<'T> is not an actual type in F# - it looks like a type (to make the language simpler), but it gets compiled to a parameter marked with the out flag. This means that byref<'T> can be only used in a place where the compiler can actually use the out flag.
The problem with function values is that you can construct function e.g. by partial application:
let foo (n:int) (b:byref<int>) =
b <- n
When you pass foo as an argument to a delegate constructor, it is a specific case of partial application (with no arguments), but partial application actually needs to construct a new method and then give that to the delegate:
type IntRefAction = delegate of byref<int> -> unit
let ac = IntRefAction(foo 5)
The compiler could be clever and generate new method with byref parameter (or out flag) and then pass that by reference to the actual function, but in general, there will be other compiler-generated method when you don't use the fun ... -> ... syntax. Handling this would add complexity and I think that's a relatively rare case, so the F# compiler doesn't do that and asks you to be more explicit...

Resources