C # से F # कोड पर कॉल करें


80

मैं F # और C # के साथ खेल रहा हूं, और C # से F # कोड कॉल करना चाहूंगा।

मैंने इसे विजुअल स्टूडियो में एक ही समाधान में दो परियोजनाएँ बनाकर और C # कोड के संदर्भ को F # प्रोजेक्ट में जोड़कर दूसरे तरीके से काम करने में कामयाबी हासिल की। ऐसा करने के बाद, मैं डिबगिंग करते समय C # कोड और यहां तक ​​कि इसके माध्यम से कदम उठा सकता था।

मैं जो करने की कोशिश कर रहा हूं वह F # से C # कोड के बजाय F # कोड F C है। मैंने F # प्रोजेक्ट का संदर्भ C # प्रोजेक्ट में जोड़ा है, लेकिन यह उस तरह से काम नहीं कर रहा है जैसा उसने पहले किया था। मैं यह जानना चाहूंगा कि क्या यह मैन्युअल रूप से किए बिना संभव है।


9
जब तक आपके पास विशिष्ट मुद्दे नहीं हैं, एक सी # एक एफ # परियोजना का एक संदर्भ जोड़कर आज "बस काम करता है"। यहां कुछ भी असाधारण नहीं है, क्योंकि यह .NET आर्किटेक्चर (भाषा अज्ञेय, एमएसआईएल आदि) के मूल वादे या लाभ में से एक है। वास्तव में, विपरीत अजीब होगा। आप इस इनाम के लिए और क्या उम्मीद करते हैं?
साइमन मूरियर

जवाबों:


57

नीचे C # से F # कॉल करने का एक कार्य उदाहरण है।

जैसा कि आपने सामना किया, मैं "संदर्भ जोड़ें ... प्रोजेक्ट्स" टैब से चयन करके एक संदर्भ जोड़ने में सक्षम नहीं था। इसके बजाय मुझे इसे "संदर्भ जोड़ें ... ब्राउज़ करें" टैब में F # असेंबली में ब्राउज़ करके मैन्युअल रूप से करना था।

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

----- मोड के लिए सी # यूनिट टीएस -----

// 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);
        }

    }
}

1
धन्यवाद। "मुझे 'संदर्भ जोड़ें ... ब्राउज़ करें' टैब में F # असेंबली में ब्राउज़ करके इसे मैन्युअल रूप से करना था।" मेरे लिए काम किया है।
ज़ीरोकेल्विन

27

यह 'सिर्फ काम' होना चाहिए, हालांकि आपको C # वर्क्स (I भूल) से प्रोजेक्ट-टू-प्रोजेक्ट संदर्भ से पहले F # प्रोजेक्ट का निर्माण करना पड़ सकता है।

मुद्दों का एक सामान्य स्रोत नामस्थान / मॉड्यूल है। यदि आपका F # कोड नेमस्पेस घोषणा के साथ शुरू नहीं होता है, तो इसे फ़ाइल नाम के समान नाम के साथ एक मॉड्यूल में रखा जाता है, ताकि C # से उदा आपका प्रकार केवल "Foo" के बजाय "Program.Foo" के रूप में दिखाई दे (यदि Foo हो) एक F # प्रकार Program.fs में परिभाषित है)।


2
मॉड्यूल नामों के बारे में जानकारी के लिए धन्यवाद :)।
ZeroKelvin

2
हाँ, मुझे यह ब्लॉग करने की आवश्यकता है कि एक, यह बहुत भ्रम का कारण बनता है।
ब्रायन

एक अतिरिक्त समस्या शुरू हो जाती है, जब Fsharp परियोजना (dll संदर्भ का जनरेटर) Csharp (उपभोक्ता परियोजना) के साथ एक ही समाधान में है
जॉर्ज कारगाकिस

6

से इस लिंक वे संभावित समाधानों की एक संख्या है, लेकिन एक है कि लग रहा था सरलतम एक टिप्पणी थी है लगता है:

एफ # कोड:

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 # कोड:

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

मुझे वैल लाइन पर एक त्रुटि मिलती है: वैल एफ 3: एफसीबैक -> इंट -> इंट -> "त्रुटि 1" अनपेक्षित कीवर्ड 'वैल' परिभाषा में। इस बिंदु या अन्य टोकन से पहले या उससे पहले अधूरे संरचित निर्माण की उम्मीद है। "
टॉम स्टिकेल

4

// 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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.