Sunday 15 April 2012

.net - What is the simplest way to access data of an F# discriminated union type in C#? -


I'm trying to understand how C # and F # can play together. I have taken some code, which basically recognizes the returning to a discriminated union type:

  type result & lt; 'Tsuccess,' tafailure & gt; = | 'TSuccess |' Success of 'Tiffiler Type Request Failure = {name: string; Email: string} IA, TestValidate input = if input.name = "" failure "name should not be empty" and success input   

while trying to consume it in C #; The only way to use values ​​against success and failure (failure is a string, success is again requested) is with the big dirty cast (which is too much typing, and the actual type is required to type which I hope I am estimated or available in metadata):

  var req = new DannyTest.Request ("Danny", "fsfs"); Var res = FSharpLib.DannyTest.TestValidate (req); If (res.IsSuccess) {Console.WriteLine ("success"); Var result = ((DannyTest.Result & lt; DannyTest.Request; string; .ability) Res. .emem; // Results is a request (as given for success) console. Published (results .mail); Console.WriteLine (result.name); } If (res.IsFailure) {Console.WriteLine ("Failure"); Var result = ((DannyTest.Result & lt; DannyTest.Request, string & gt; Failure) Res) .emem; // The result is a string (as has been returned for failure) Console.WriteLine (Results); }   

Is there a better way to do this? Even if I have to manually insert (with the possibility of a runtime error), I hope the minimum type of access ( DannyTest.Result & lt; DannyTest.Request, string & Gt; failure ). Is there a better way?

Working with unions with discrimination will never be straightforward in one language does not support pattern matching However, your results & lt; 'TSuccess,' TFailure & gt; The type is quite simple that it should be a good way to use C # (if the type was somewhat more complex, like the expression tree, then I might suggest using a visitor pattern ).

Others have already mentioned some options - both can directly use the value and how can match define the method (as the blog of Mauricio Is described in the post). My preferred method for simple DU is to define TryGetXyz methods that follow the same style of Int32.TryParse - also guarantees that the C # developers pattern Will be familiar with F # Definition looks like this:

  open system. time. Intertop Services Type Result & lt; 'TSUX,' TFile & gt; = | 'TSuccess |' The success of 'tiffisher type results & lt;' Tesufas, 'tifylur & gt; Member x.TryGetSuccess ([& lt; Out & gt;] with success: byref & lt; 'Tsuccess & gt;) = With Match X. Success value - & gt; Success and lieutenant; - value; True | _ - & gt; False member x.TryGetFailure ([& lt; out & gt; failure: byref & lt; 'TFailure & gt;) = with Match X. Failure value - & gt; Failure & lt; - Values; True | _ - & gt; Incorrect   

This returns back to the extension TryGetSuccess and TryGetFailure true Matching and withdrawal of Discriminated Union case through the Out parameters (C) The use of C # is quite straightforward for all those people who ever TryParse : < / P>

  int succ; String failed; If (res.TryGetSuccess (succ out)) {Console.WriteLine ("Success: {0}", succ); } And if (res.TryGetFailure (failed out)) {Console.WriteLine ("Failuere: {0}", unsuccessful); }   

I think the introduction of this method is the most important benefit. When you use F # and use it for C # developers, you should display them in the most direct way (C # users should not think that the type defined in F # Are non-standard).

In addition to this, it gives you a reasonable guarantee (when used properly) that you will actually be able to access those values ​​when the DU matches a particular case.

No comments:

Post a Comment