编辑:我同时reported this到F#团队。虽然没有得到答案并不一定意味着这是一个错误,但我在下面重新评估了我自己的问题,至少部分问题没有意义。随意纠正我;)。
以下问题的解决方法是微不足道的,但我对通过展示一些渐进式示例最能解释的行为的原因感兴趣:
所有示例都包含以下内容:
[<AutoOpen>]
module SystemExt =
open System
let parseInt = Int64.TryParse
type Option<'T> with
/// Creates an Option from a .NET byref result, (true, res) -> Some res, otherwise None
static member ofByRef (success, result) =
match success with
| true -> Some result
| _ -> None
type Int64 with
static member TryParse = parseInt >> Option.ofByRef
let test1 =
Int64.TryParse "42"
|> Option.map ((*) 2L) // won't compile, type error
不同的语法,参数的冗余重复,但这会编译,前面的例子没有:
type Int64 with
static member TryParse s = (parseInt >> Option.ofByRef) s
let test1 =
Int64.TryParse "42"
|> Option.map ((*) 2L) // compiles fine
我对这个编译感到有些惊讶,但也许第一个被编译成一个属性,第二个被编译成一个方法,所以也许这就解释了它(虽然通常两个具有不同签名的函数通常是无效的)。
type Int64 with
static member TryParse = parseInt >> Option.ofByRef
static member TryParse s = (parseInt >> Option.ofByRef) s
let test1 =
Int64.TryParse "42"
|> Option.map ((*) 2L)
我无法解释这个,差异只在第一行,使用原始函数Int64.TryParse
。
type Int64 with
static member TryParse = Int64.TryParse >> Option.ofByRef
static member TryParse s = (parseInt >> Option.ofByRef) s // type error
let test1 =
Int64.TryParse "42"
|> Option.map ((*) 2L) // type error
let test1 =
Int64.get_TryParse() "42" // compiles fine, why the need to be
// explicit using the property accessor?
|> Option.map ((*) 2L)
这是我的出发点,导致上面的其他实验,我仍然没有“得到”这个。
type Int64 with
static member TryParse = Int64.TryParse >> Option.ofByRef
let test1 =
Int64.TryParse "42"
|> Option.map ((*) 2L) // type error
第六个例子的变体
type Int64 with
static member TryParse s = (Int64.TryParse >> Option.ofByRef) s // type error
let test1 =
Int64.TryParse "42" // type error
|> Option.map ((*) 2L)
最后一个例子(第七个)似乎错误地推断出Int64.TryParse
方法的类型,并最终以递归方式调用自身,从而导致类型错误。
我不明白为什么会发生这种情况,解决的顺序是,iirc,类成员在扩展之前进行,在模糊的情况下,成员优先。
第六和第七之间的差异很奇怪。延长线在第六个编译,但不在第七个编译。虽然没有标准方法可以调用第六个例子中重写的TryParse
方法。