hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Using F#-Functions in C#

Last post 09-10-2008, 5:21 by forki23. 8 replies.
Sort Posts: Previous Next
  •  09-08-2008, 1:37 6967

    Using F#-Functions in C#

    Hi,

    I have a module "MyModule.fs" with:

    let f1 a b = a * b
    let f2 a b = a + b

    let f3 f a b = f a b

    Now I can use the function (inside F#-Code) like this:

    let a = MyModule.f3 MyModule.f2 10 20
    a |> printfn "%A"

    When I try to get this into C# I get a compile-error:
    int a = MyModule.f3(MyModule.f2, 10, 20));

    Error 1 The type arguments for method 'MyModule.f3(Microsoft.FSharp.Core.FastFunc>, T, U)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
    When I use Reflector on the F#-Code then the get:


    [CompilationMapping(SourceConstructFlags.Module)]
    public static class Program
    {
        // Properties
        [CompilationMapping(SourceConstructFlags.Value)]
        public static ConsoleKeyInfo a
        {
            get
            {
                return $Program.a@28;
            }
        }

        [CompilationMapping(SourceConstructFlags.Value)]
        public static int t
        {
            get
            {
                return $Program.t@24;
            }
        }

        // Nested Types
        [Serializable]
        internal class clo@24 : OptimizedClosures.FastFunc2<int, int, int>
        {
            // Methods
            public override int Invoke(int a@595, int b@595)
            {
                return Euler.f2(a@595, b@595);
            }
        }
    }

    public static void _main() {
      t@24 = MyModule.f3(new Program.clo@24(), 10, 20);
      int num = Program.get_t();
      FastFunc func = Pervasives.printfn>(
         new Format, TextWriter, Unit, Unit, int>("%A"));
      int num2 = num;
      func.Invoke(num2);
      a@28 = Console.ReadKey();
    }

    What can I do?
  •  09-08-2008, 4:42 6969 in reply to 6967

    Re: Using F#-Functions in C#

    It's because FastFunc isn't a delegate type, you'll need to convert your delegate using the FuncConvert.ToFastFunc.

    Cheers,
    Rob


    Robert Pickering, MVP
    http://strangelights.com
  •  09-08-2008, 5:11 6970 in reply to 6969

    Re: Using F#-Functions in C#

    Thanks Rob. Can you write a piece of code how you would convert the function MyModule.f2 in this sample?
  •  09-08-2008, 6:12 6972 in reply to 6970

    Re: Using F#-Functions in C#

    It's actually harder than I thought:

    int a = Module1.f3(FuncConvert.FuncFromTupled(FuncConvert.ToFastFunc(delegate(Tuple ab) { return Module1.f2(ab.Item1, ab.Item2); })), 10, 20);


    You need to supply an anonymous delegate that takes a tuple of arguments then wrap this in FuncConvert.ToFastFunc and then FuncConvert.FuncFromTupled.

    Cheers,
    Rob
    Robert Pickering, MVP
    http://strangelights.com
  •  09-08-2008, 6:57 6976 in reply to 6972

    Re: Using F#-Functions in C#

    Hi,
    just a short addition - if your primary goal is to use the library from C# then it may be worth to design it in a more "C#-friendly" way. Instead of using F# functions in the arguments, you can declare delegate type and using the functions from C# will then be straightforward:


    > type FCallback = delegate of int*int -> int;;
    type FCallback =
      delegate of int * int -> int

    > let f3 (f:FCallback) a b = f.Invoke(a,b);;
    val f3 : FCallback -> int -> int -> int

    The C# code could then use the usual style:


    int a = Module1.f3(Module1.f2, 10, 20); // method gets converted to the delegate automatically in C#

    Hope this helps!
    T.


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  09-08-2008, 8:21 6977 in reply to 6976

    Re: Using F#-Functions in C#

    Thanks a lot.

    @tomasp:
    - but with your method I can't write my call in F#:
      let a = MyModule.f3 MyModule.f2 10 20
  •  09-08-2008, 8:41 6978 in reply to 6977

    Re: Using F#-Functions in C#

    Ok my MyModule is now:

    let f3 f a b = f a b

    let f1 a b = a * b
    let f2 a b = a + b 

    let t1 = f3 f1 10 20
    let t2 = f3 f2 10 20

    and in C#:

                var f2 =
                    FuncConvert.FuncFromTupled(
                      FuncConvert.ToFastFunc((Tuple<int, int> ab) => MyModule1.f2(ab.Item1, ab.Item2)));

                var f1 =
                    FuncConvert.FuncFromTupled(
                      FuncConvert.ToFastFunc((Tuple<int, int> ab) => MyModule1.f1(ab.Item1, ab.Item2)));

                int a = MyModule1.f3(f2, 10, 20);
                Console.WriteLine(a);

                a = MyModule1.f3(f1, 10, 20);
                Console.WriteLine(a);
                Console.ReadKey();

    This works correct, but maybe there is a better solution....
  •  09-08-2008, 8:51 6979 in reply to 6978

    Re: Using F#-Functions in C#

    I think Tomas' solution is going in the right direction, you can call f3 from F# but it's a little more complex:
    [code langauge="F#"]f3 (new FCallback(fun a b -> f2 a b)) 10 20;;[/code]

    So you'd probably just create a version to be used from F#:
    [code langauge="F#"]let f3' f = f3 (new FCallback(f));;[/code]

    Robert Pickering, MVP
    http://strangelights.com
  •  09-10-2008, 5:21 7024 in reply to 6979

    Re: Using F#-Functions in C#

    Thank you very much.
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems