Klark
Klark

Reputation: 8280

F# operator overloading strange behavoir

Let's say that for some strange reason I want to have this function:

let (~-) (str:string) = 42

So I can do something like this and get 42 as result:

-"test"
val it : int = 42

Which is fine. But now when I do:

let a = 100
-a

I get:

error FS0001: This expression was expected to have type
    string    
but here has type
    int    

Any idea why is this happening?

Upvotes: 2

Views: 116

Answers (2)

Fsharp Pete
Fsharp Pete

Reputation: 751

Simply, you overwrote the minus operator with one that takes a string and returns an int, then tried to apply it to an int, which it can't do anymore.

Upvotes: 1

Tomas Petricek
Tomas Petricek

Reputation: 243041

When you define operators using let, the new definition hides all previous definition of the operator. So in your example, you are hiding the default implementation of the unary minus (which works for numbers) and replacing it with a new operator that only works on strings.

It is not easy to re-define overloaded operators on built-in types. If you need that, it is probably better idea to avoid using operators (just use a function). However, if you want to provide an overloaded operator for a custom type, you can do this by adding operator as a static member:

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"

If you really want to redefine built-in operator like unary minus and make it work on string, then there is actually a way to do this using a trick described in earlier SO answers. However, I would only use this if you have a good reason.

Upvotes: 7

Related Questions