为什么这两种方法的签名不同?
问题描述:
为什么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#有所回暖非泛型类型v
和f
,其默认为obj
。您可以选择其他特定类型并使用类型注释为Bind1
提供不同的(但仍是非通用的)签名。