Reputation: 21727
I made a function in F#
let tryParseArray tryParse (separator:char) (line: string) =
// inside the function I use the tuple form of tryParse
It works fine if I call it in such way: tryParseArray Int32.TryParse ',' "2,3,2,3,2"
Now I would like this function to be available in C# as well, so I did this:
static member TryParseArray (line, tryParse, separator) =
line |> tryParseArray tryParse separator
Then I realized that TryParseArray
actually takes tryParse
argument as FSharpFunc
, which is not friendly to C# at all, so I tried this:
static member TryParseArray (line, [<Out>] tryParse: (string * byref<'a> -> bool), separator) =
line |> tryParseArray tryParse separator
but now tryParseArray
doesn't accept tryParse
as a valid argument (type error)
What should I do?
I wish in C# I can call TryParseArray("2,3,2,3,2", Int32.TryParse, ',')
as well
Upvotes: 1
Views: 232
Reputation: 47904
desco's solution is good, but if you wanted to avoid byref
you could do something like this:
type TryParse<'R> = delegate of string -> bool * 'R
module Util =
[<CompiledName("TryParseArray")>]
let tryParseArray (tryParse: TryParse<_>) (separator:char) (line: string) = ...
which can be called from F# like this:
let res = Util.tryParseArray (TryParse(Int32.TryParse)) ',' "1,2,3"
and, with the following wrapper method:
static class TryParse {
public static Tuple<bool, int> Int32(string s) {
int i;
var b = System.Int32.TryParse(s, out i);
return Tuple.Create(b, i);
}
}
like this, from C#:
var res = Util.TryParseArray(TryParse.Int32, ',', "1,2,3");
Upvotes: 0
Reputation: 16782
You can expose this function to C# using custom delegate type :
EDITED
// F#
module Lib
let tryParseArray parser (line : string) (sep : char) =
// don't know your exact implementation so again just guessing...
line.Split sep
|> Array.choose (fun el ->
match parser el with
| true, el -> Some el
| false, _ -> None
)
open System.Runtime.InteropServices
type TryParse<'R> = delegate of str : string * [<Out>] res : byref<'R> -> bool
type T =
static member TryParse(line : string, tryParse : TryParse<'R>, separator : char) : 'R[] =
tryParseArray tryParse.Invoke line separator
//C#
var r = Lib.T.TryParse<int>("1,2,3", int.TryParse, ',');
NOTE: on the C# side you'll need to specify type parameter for TryParse explicitly (Why don't anonymous delegates/lambdas infer types on out/ref parameters?)
Upvotes: 5