2009-12-21 3 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 

Это произошло, когда я играл с некоторыми выражениями вычислений и не мог понять, почему я получаю сообщение об ошибке о 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, (с) Microsoft Corporation, All Rights Reserved F # Version 1.9.7.4, компиляцией для .NET Framework версии v4.0.21006

ответ

7

Bind1 - свойство get, которое возвращает функцию, а bind2 - это функция. Вы можете увидеть get accessor, если вы оцениваете bind1 и bind2 из экземпляра.

> 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

Чтобы уточнить ответ Эрика, потому что невозможно иметь общие свойства на объекты .NET, F # должен выбрать необщего типов для v и f, которые по умолчанию obj. Вы можете выбрать другие конкретные типы и использовать аннотацию типа, чтобы дать Bind1 другую (но все же не общую) подпись.

Смежные вопросы