为什么这两种方法的签名不同?

问题描述:

为什么Bind1和Bind2有不同的签名?为什么这两种方法的签名不同?

type T() = 
    let bind(v, f) = v 
    member self.Bind1 = bind 
    member self.Bind2(a, b) = bind(a, b) 

FSI报告他们作为

type T = 
    class 
    new : unit -> T 
    member Bind2 : a:'a * b:'b -> 'a 
    member Bind1 : (obj * obj -> obj) 
    end 

在此之前,当我与一些计算表达式玩,无法弄清楚,为什么我得到约没有被定义绑定的错误消息。 Bind1风格不起作用,Bind2做到了,我无法弄清楚为什么。

由于相同的对象,他们返回相同的结果:

> q.Bind1(1:>obj,3:>obj);; 
val it : obj = 1 
> q.Bind2(1:>obj,3:>obj);; 
val it : obj = 1 
> 

使用Microsoft F#互动,(c)Microsoft公司,保留所有权利 F#版本1.9.7.4,编译为.NET Framework版本v4.0.21006

Bind1是一个get属性,返回一个函数,而bind2是一个函数。如果您评估实例的bind1和bind2,则可以看到get访问器。

> let t = new T();; 
val t : T 
> t.Bind1;; 
val it : (obj * obj -> obj) = <fun:[email protected]> 
> t.Bind2;; 
val it : ('a * 'b -> 'a) = <fun:[email protected]> 

你写的

member self.Bind1 
    with get() = bind 

速记使用reflector你可以在Bind1看到这里的obj来自和函数对象。

internal class [email protected] : FSharpFunc<Tuple<object, object>, object> 
{ 
    // Fields 
    public T self; 

    // Methods 
    internal [email protected](T self) 
    { 
     this.self = self; 
    } 

    public override object Invoke(Tuple<object, object> tupledArg) 
    { 
     object v = tupledArg.get_Item1(); 
     object f = tupledArg.get_Item2(); 
     return this.self.bind<object, object>(v, f); 
    } 
} 

随着什么kvb说,你可以添加类型注释到类,以避免通用的对象。

type T<'a, 'b>() = 
    let bind(v:'a, f:'b) = (v:'a) 
    member self.Bind1 = bind 
    member self.Bind2(a, b) = bind(a, b) 

type T<'a,'b> = 
    class 
    new : unit -> T<'a,'b> 
    member Bind2 : a:'a * b:'b -> 'a 
    member Bind1 : ('a * 'b -> 'a) 
    end 

为了详细说明Erik的答案,因为它是不可能对.NET对象一般属性,F#有所回暖非泛型类型vf,其默认为obj。您可以选择其他特定类型并使用类型注释为Bind1提供不同的(但仍是非通用的)签名。