С точки зрения эквивалентности, функции не имеют значимой сериализации.
Curryable функции в F # реализованы как производные от FSharpFunc
.
let la = (fun x y -> x + y + foo)
будет быть реализован как экземпляр следующего класса (в эквиваленте C#):
[Serializable] class Impl : FSharpFunc<int, int, int>
{
public int foo;
Impl(int foo_) => foo = foo_;
public override int Invoke(int x, int y) =>
x + y + _foo;
}
Что захватывает двоичная сериализация будет полное имя типа и значение foo. Фактически, если мы посмотрим на строки в потоке байтов, мы увидим:
test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Program+la@28
foo
... где la@28
- имя нашего производного класса.
Где поток байтов для la
и lb
отличается - это имя реализующего класса. Реализации la
и lb
могут быть совершенно разными.
Вы можете, например, изменить lb
на let lb = (fun x y -> x * y + foo)
, и результат будет одинаковым для обоих прогонов.
Однако вы можете сделать это с Цитаты кода :
let foo = 10
let la = <@ fun x y -> x + y + foo @>
let lb = <@ fun x y -> x + y + foo @>
printfn "Is same: %b" (la.ToString() = lb.ToString()) //true
F # также поддерживает Expression<Func<>>
(деревья выражений C#), что также является допустимым способом сравнения.