Wywołanie funkcji f # wyższego rzędu z C#

Biorąc pod uwagę funkcję wyższego rzędu F# (przyjmując funkcję w parametrze):

let ApplyOn2 (f:int->int) = f(2)  

I funkcja C#

public static int Increment(int a) { return a++; } 

Jak wywołać ApplyOn2 z Increment jako parametr (z C#)? Zauważ, że {[2] } jest eksportowane jako Microsoft.FSharp.Core.FSharpFunc<int,int>, które nie pasują do podpisu Increment.

Author: CodesInChaos, 2009-12-23

3 answers

Jeśli chcesz zapewnić bardziej przyjazne doświadczenie interop, rozważ użycie systemu.Functional type directly in F#:

let ApplyOn2 (f : System.Func<int, int>) = f.Invoke(2)

Byłabyś w stanie bardzo łatwo wywołać funkcję F# W C# w następujący sposób:

MyFSharpModule.ApplyOn2(Increment); // 3

Jest jednak problem z funkcją inkrementacji, tak jak ją napisałeś. Aby funkcja zwracała poprawny wynik, potrzebna jest forma przedrostka operatora inkrementacji:

public static int Increment(int a) { return ++a; }
 17
Author: Ray Vernagus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 13:29:50

Aby uzyskać FSharpFunc z równoważnej funkcji C# użyj:

Func<int,int> cs_func = (i) => ++i;
var fsharp_func = Microsoft.FSharp.Core.FSharpFunc<int,int>.FromConverter(
    new Converter<int,int>(cs_func));

Aby uzyskać funkcję C# z równoważnego FSharpFunc, użyj

var cs_func = Microsoft.FSharp.Core.FSharpFunc<int,int>.ToConverter(fsharp_func);
int i = cs_func(2);

Więc w tym konkretnym przypadku twój kod może wyglądać następująco:

Func<int, int> cs_func = (int i) => ++i;
int result = ApplyOn22(Microsoft.FSharp.Core.FSharpFunc<int, int>.FromConverter(
            new Converter<int, int>(cs_func)));
 29
Author: HS.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 12:12:50

Po prostu utwórz odniesienie do swojego zestawu:

#r @"Path\To\Your\Library.dll"
let ApplyOn2 (f:int->int) = f(2)
ApplyOn2 Library.Class.Increment
 -2
Author: ssp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 11:29:58