F#运算符重载奇怪的行为

Kla*_*ark 2 f#

让我们说,由于一些奇怪的原因,我希望有这个功能:

let (~-) (str:string) = 42
Run Code Online (Sandbox Code Playgroud)

所以我可以做这样的事情,得到42结果:

-"test"
val it : int = 42
Run Code Online (Sandbox Code Playgroud)

哪个好.但现在我这样做:

let a = 100
-a
Run Code Online (Sandbox Code Playgroud)

我明白了:

error FS0001: This expression was expected to have type
    string    
but here has type
    int    
Run Code Online (Sandbox Code Playgroud)

知道为什么会这样吗?

Tom*_*cek 7

使用时定义运算符时let,新定义会隐藏运算符的所有先前定义.因此,在您的示例中,您隐藏了一元减号的默认实现(适用于数字),并将其替换为仅适用于字符串的新运算符.

在内置类型上重新定义重载运算符并不容易.如果您需要,最好避免使用运算符(只需使用函数).但是,如果要为自定义类型提供重载运算符,可以通过将运算符添加为静态成员来执行此操作:

type MinusString(s:string) =
  member x.Value = s
  /// Provide unary minus for MinusString values
  static member (~-) (ms:MinusString) =
    MinusString("-" + ms.Value)

-(MinusString "hi") // Returns "-hi"
Run Code Online (Sandbox Code Playgroud)

如果你真的想要重新定义内置运算符(如一元减号)并使其正常工作string,那么实际上有一种方法可以使用早期SO答案中描述技巧来实现.但是,如果你有充分的理由,我只会使用它.