Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call F# code from C#

Tags:

c#

interop

f#

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 projects in the same solution, and adding a reference of the C# code to the F# project. After doing this, I could call C# code and even step through it while debugging.

What I am trying to do is F# code FROM C# instead of C# code from F#. I added a reference to the F# project to the C# project, but it isn't working the way it did before. I would like to know if this is possible without doing it manually.

like image 781
ZeroKelvin Avatar asked Jan 25 '09 23:01

ZeroKelvin


People also ask

Call of Duty buatan siapa?

Call of Duty: Mobile, biasa disingkat menjadi COD:M atau CODM adalah permainan video tembak-menembak orang-pertama gratis yang dikembangkan oleh Timi Studio (anak perusahaan Tencent), dan diterbitkan oleh Activision dan Garena untuk serambi Android dan iOS. Dirilis pada 1 Oktober 2019, permainan ini melihat salah satu ...

COD di buat kapan?

Call of Duty adalah waralaba permainan video penembak orang pertama yang diterbitkan oleh Activision. Dimulai pada tahun 2003, pertama kali berfokus pada permainan yang berlatar Perang Dunia II.

Berapa GB game Call of Duty?

Pasalnya diketahui sejauh ini Call of Duty: Mobile menghabiskan cukup banyak ruang penyimpanan di smartphone, yakni sekitar 5,5 GB. Ukuran tersebut jelas jauh lebih besar jika dibandingkan dengan gim-gim rivalnya di Indonesia seperti PUBG Mobile dan Free Fire.


2 Answers

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);         }      } } 
like image 190
Eric Avatar answered Sep 17 '22 21:09

Eric


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).

like image 30
Brian Avatar answered Sep 18 '22 21:09

Brian