Вернуть FSharpFunc из F # в C # - PullRequest
3 голосов
/ 11 октября 2011

Я хочу написать функцию на F #, которая предоставляет следующую сигнатуру типа для C #:

public static FSharpFunc<FSharpFunc<Unit,Unit>,Unit> foo(Action<Action> f)

В F # я пытался написать:

let foo (f : Action<Action>) : ((unit -> unit) -> unit) = ...

Но это создает сигнатуру C #:

public static void foo(Action<Action> f, FSharpFunc<Unit,Unit> x)

F # обработал мой код эквивалентно:

let foo (f : Action<Action>) (g : unit -> unit) : unit = ...

Конечно, они эквивалентны F #, но сильно отличаются в C #. Что я могу сделать, чтобы создать C #, который я хочу? (F # 2.0.0.0)

В качестве быстрого взлома я переписал свой F # на:

let foo (f : Action<Action>) ((unit -> unit) -> unit)[] = ...

Тогда я просто использую Head в C #.

Ответы [ 3 ]

2 голосов
/ 11 октября 2011

Или:

  1. Добавить файл подписи, с val foo : Action<Action> -> ((unit -> unit) -> unit).
  2. Используйте статический член номинального типа, а не значение с привязкой в ​​модуле. То есть static member foo (x:Action<Action>) : ((unit -> unit) -> unit) = ...
2 голосов
/ 11 октября 2011

Если вы напишите let foo x = fun () -> ..., то компилятор F # оптимизирует код и скомпилирует его как метод, который принимает два аргумента (вместо метода, возвращающего функцию, которая вам нужна).Чтобы получить значение функции в качестве результата, вам нужно «сделать что-то» перед возвратом функции:

// Will be compiled as method taking Action, FastFunc and returning void
let foo1(x : Action<Action>) : (unit -> unit) -> unit = 
  fun f -> f ()

// Will be compiled as method taking Action and returning FastFunc of FastFunc
let foo2(x : Action<Action>) : ((unit -> unit) -> unit) = 
  ignore ();
  fun f -> f ()

Тем не менее, подвергание типа функции F # C # любым способом является плохим шаблоном и это не должно быть сделано.Когда у вас есть некоторый API F #, который предполагается использовать из C #, вы должны предоставлять функции в качестве делегатов, чтобы потребители C # могли использовать их естественным образом (без явного преобразования Action в функцию F #).Обычно проще написать перенос на стороне F #.

0 голосов
/ 11 октября 2011

как то так?

open System 
let foo(x : Action<Action>) : (unit -> unit) -> unit = failwith "..."
...