2009-12-21 72 views
3

爲什麼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

回答

7

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 
4

爲了詳細說明Erik的答案,因爲它是不可能對.NET對象一般屬性,F#有所回暖非泛型類型vf,其默認爲obj。您可以選擇其他特定類型並使用類型註釋爲Bind1提供不同的(但仍是非通用的)簽名。

相關問題