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
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
{
public static List mkList(params T[] ar)
{
List foo = List.Nil;
for (int n = ar.Length - 1; n >= 0; n--)
foo = List.Cons(ar[n], foo);
return foo;
}
}
[Test]
public void foldl1()
{
int seed = 64;
List values = Helper.mkList( 4, 2, 4 );
FastFunc> fn =
FuncConvert.ToFastFunc( (Converter) delegate( int a, int b ) { return a/b; } );
int result = Zumbro.foldl( fn, seed, values);
Assert.AreEqual(2, result);
}
[Test]
public void foldl0()
{
string seed = "hi mom";
List values = Helper.mkList();
FastFunc> fn =
FuncConvert.ToFastFunc((Converter)delegate(string a, string b) { throw new Exception("should never be invoked"); });
string result = Zumbro.foldl(fn, seed, values);
Assert.AreEqual(seed, result);
}
[Test]
public void map()
{
FastFunc fn =
FuncConvert.ToFastFunc((Converter)delegate(int a) { return a*a; });
List vals = Helper.mkList(1, 2, 3);
List res = Zumbro.map(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 vals = Helper.mkList("arnold", "BOB", "crAIg");
List exp = Helper.mkList( "ARNOLD", "BOB", "CRAIG" );
List 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);
}
}
}