比较F#中的函数类型

jru*_*ren 1 f#

下一次测试失败.我直接将GetType调用到函数定义,然后我也在内联函数中调用GetType.生成的类型不相等.

namespace PocTests

open FsUnit
open NUnit.Framework

module Helpers = 
    let balance ing gas = ing - gas

[<TestFixture>] 
type ``Reflected types`` ()=

    [<Test>] member x.
        ``test type equality with inline use`` () =
            let inline (=>) f = f.GetType().FullName, f in
            let fullName, fval = (=>) Helpers.balance in
            Helpers.balance.GetType().FullName |> should equal (fullName)
Run Code Online (Sandbox Code Playgroud)

我怎么能得到相同的类型才能"可比".

Tom*_*cek 6

当您将函数用作值时,F#不会保证两个创建的对象将是"相同的".在封面下,编译器为每个实例创建一个新的闭包对象,因此false即使你尝试这样的事情,你也会得到结果:

balance.GetType().FullName = balance.GetType().FullName
Run Code Online (Sandbox Code Playgroud)

这是预期的行为 - 当您尝试直接比较函数时,编译器将告诉您函数不满足等式约束并且无法进行比较:

> let balance ing gas = ing - gas;;
val balance : ing:int -> gas:int -> int

> balance = balance;;
error FS0001: The type '(int -> int -> int)' does not support the 
'equality' constraint because it is a function type
Run Code Online (Sandbox Code Playgroud)

这意味着您问题的最佳答案是您无法完成的要求.我认为比较函数值很可能不是一个好主意,但如果您提供更多详细信息,为什么要这样做,也许对您的特定问题有更好的答案.

如果您真的想对函数值执行相等测试,那么最简洁的方法可能是定义接口并测试普通对象的相等性:

type IFunction = 
  abstract Invoke : int * int -> int
let wrap f = 
  { new IFunction with
      member x.Invoke(a, b) = f a b }
Run Code Online (Sandbox Code Playgroud)

现在,您可以将该balance函数包装在可以比较的接口实现中:

let balance ing gas = ing - gas
let f1 = wrap balance
let f2 = f1
let f3 = wrap balance
f1 = f2 // These two are the same object and are equal
f1 = f3 // These two are different instances and are not equal
Run Code Online (Sandbox Code Playgroud)