Call F# code from C#

前端 未结 4 1727
抹茶落季
抹茶落季 2020-12-04 07:13

I am playing around with F# and C#, and would like to call F# code from C#.

I managed to get it to work the other way around in Visual Studio by having two project

相关标签:
4条回答
  • 2020-12-04 07:30

    // Test.fs :

    module meGlobal
    
    type meList() = 
        member this.quicksort = function
            | [] -> []  //  if list is empty return list
            | first::rest -> 
                let smaller,larger = List.partition((>=) first) rest
            List.concat[this.quicksort smaller; [first]; this.quicksort larger]
    

    // Test.cs :

    List<int> A = new List<int> { 13, 23, 7, 2 };
    meGlobal.meList S = new meGlobal.meList();
    
    var cquicksort = Microsoft.FSharp.Core.FSharpFunc<FSharpList<IComparable>,     FSharpList<IComparable>>.ToConverter(S.quicksort);
    
    FSharpList<IComparable> FI = ListModule.OfSeq(A.Cast<IComparable>());
    var R = cquicksort(FI);
    
    0 讨论(0)
  • 2020-12-04 07:37

    It should 'just work', though you might have to build the F# project before a project-to-project reference from C# works (I forget).

    A common source of issues is namespaces/modules. If your F# code does not start with a namespace declaration, it gets put in a module with the same name as the filename, so that e.g. from C# your type might appear as "Program.Foo" rather than just "Foo" (if Foo is an F# type defined in Program.fs).

    0 讨论(0)
  • 2020-12-04 07:40

    From this link they seem to have a number of possible solutions, but the one that seemed the simplest was a comment:

    F# Code:

    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
    

    C# Code:

    int a = Module1.f3(Module1.f2, 10, 20); // method gets converted to the delegate automatically in C#
    
    0 讨论(0)
  • 2020-12-04 07:52

    Below is a working example of calling F# from C#.

    As you encountered, I was not able to add a reference by selecting from the "Add Reference ... Projects" tab. Instead I did have to do it manually, by browsing to the F# assembly in the "Add Reference ... Browse" tab.

    ------ F# MODULE -----

    // First implement a foldl function, with the signature (a->b->a) -> a -> [b] -> a
    // Now use your foldl function to implement a map function, with the signature (a->b) -> [a] -> [b]
    // Finally use your map function to convert an array of strings to upper case
    //
    // Test cases are in TestFoldMapUCase.cs
    //
    // Note: F# provides standard implementations of the fold and map operations, but the 
    // exercise here is to build them up from primitive elements...
    
    module FoldMapUCase.Zumbro
    #light
    
    
    let AlwaysTwo =
       2
    
    let rec foldl fn seed vals = 
       match vals with
       | head :: tail -> foldl fn (fn seed head) tail
       | _ -> seed
    
    
    let map fn vals =
       let gn lst x =
          fn( x ) :: lst
       List.rev (foldl gn [] vals)
    
    
    let ucase vals =
       map String.uppercase vals
    

    ----- C# UNIT TESTS FOR THE MODULE -----

    // Test cases for FoldMapUCase.fs
    //
    // For this example, I have written my NUnit test cases in C#.  This requires constructing some F#
    // types in order to invoke the F# functions under test.
    
    
    using System;
    using Microsoft.FSharp.Core;
    using Microsoft.FSharp.Collections;
    using NUnit.Framework;
    
    namespace FoldMapUCase
    {
        [TestFixture]
        public class TestFoldMapUCase
        {
            public TestFoldMapUCase()
            {            
            }
    
            [Test]
            public void CheckAlwaysTwo()
            {
                // simple example to show how to access F# function from C#
                int n = Zumbro.AlwaysTwo;
                Assert.AreEqual(2, n);
            }
    
            class Helper<T>
            {
                public static List<T> mkList(params T[] ar)
                {
                    List<T> foo = List<T>.Nil;
                    for (int n = ar.Length - 1; n >= 0; n--)
                        foo = List<T>.Cons(ar[n], foo);
                    return foo;
                }
            }
    
    
            [Test]
            public void foldl1()
            {
                int seed = 64;
                List<int> values = Helper<int>.mkList( 4, 2, 4 );
                FastFunc<int, FastFunc<int,int>> fn =
                    FuncConvert.ToFastFunc( (Converter<int,int,int>) delegate( int a, int b ) { return a/b; } );
    
                int result = Zumbro.foldl<int, int>( fn, seed, values);
                Assert.AreEqual(2, result);
            }
    
            [Test]
            public void foldl0()
            {
                string seed = "hi mom";
                List<string> values = Helper<string>.mkList();
                FastFunc<string, FastFunc<string, string>> fn =
                    FuncConvert.ToFastFunc((Converter<string, string, string>)delegate(string a, string b) { throw new Exception("should never be invoked"); });
    
                string result = Zumbro.foldl<string, string>(fn, seed, values);
                Assert.AreEqual(seed, result);
            }
    
            [Test]
            public void map()
            {
                FastFunc<int, int> fn =
                    FuncConvert.ToFastFunc((Converter<int, int>)delegate(int a) { return a*a; });
    
                List<int> vals = Helper<int>.mkList(1, 2, 3);
                List<int> res = Zumbro.map<int, int>(fn, vals);
    
                Assert.AreEqual(res.Length, 3);
                Assert.AreEqual(1, res.Head);
                Assert.AreEqual(4, res.Tail.Head);
                Assert.AreEqual(9, res.Tail.Tail.Head);
            }
    
            [Test]
            public void ucase()
            {
                List<string> vals = Helper<string>.mkList("arnold", "BOB", "crAIg");
                List<string> exp = Helper<string>.mkList( "ARNOLD", "BOB", "CRAIG" );
                List<string> res = Zumbro.ucase(vals);
                Assert.AreEqual(exp.Length, res.Length);
                Assert.AreEqual(exp.Head, res.Head);
                Assert.AreEqual(exp.Tail.Head, res.Tail.Head);
                Assert.AreEqual(exp.Tail.Tail.Head, res.Tail.Tail.Head);
            }
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题