为什么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
当我正在使用一些计算表达式时出现这种情况,并且无法弄清楚为什么我收到有关Bind未定义的错误消息。 Bind1风格不起作用,Bind2做了,我无法弄清楚原因。
给定相同的对象,它们会返回相同的结果:
> q.Bind1(1:>obj,3:>obj);;
val it : obj = 1
> q.Bind2(1:>obj,3:>obj);;
val it : obj = 1
>
使用Microsoft F#Interactive,(c)Microsoft Corporation,保留所有权利 F#版本1.9.7.4,编译.NET Framework版本v4.0.21006
答案 0 :(得分:7)
Bind1是一个get属性,返回一个函数,而bind2是一个函数。如果从实例中评估bind1和bind2,则可以看到get访问器。
> let t = new T();;
val t : T
> t.Bind1;;
val it : (obj * obj -> obj) = <fun:get_Bind1@3>
> t.Bind2;;
val it : ('a * 'b -> 'a) = <fun:it@10>
你写了
的简写member self.Bind1
with get() = bind
使用reflector,您可以在Bind1中看到obj来自哪里以及函数对象。
internal class get_Bind1@7 : FSharpFunc<Tuple<object, object>, object>
{
// Fields
public T self;
// Methods
internal get_Bind1@7(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
答案 1 :(得分:4)
详细说明Erik的答案,因为在.NET对象上不可能有通用属性,F#必须选择v
和f
的非泛型类型,默认为{{1} }。您可以选择其他特定类型并使用类型注释为obj
提供不同的(但仍然是非通用的)签名。