17

If I have a C# class with implicit conversion to double, like so:

public class Parameter
{
    private double _value;
    public Parameter(double value) { _value = value }
    public static implicit operator double(Parameter p) { return _value; }
}

F# doesn't like me trying to use it as if it were a float:

let a = Parameter(4.0)
let b = Parameter(2.0)
let c = a * Math.Sin(b) <-- 'expected float, here Parameter'

Is there any way to do this (I'm guessing there isn't, based on this question/answer), and if not, what would be a decent workaround?

Community
  • 1
  • 1
Benjol
  • 63,995
  • 54
  • 186
  • 268
  • Thinks: I can add a `Value` property and use that everywhere, it's not beautiful, but less ugly that anything else I can think of... – Benjol May 23 '12 at 12:22
  • 1
    Sadly not...http://stackoverflow.com/questions/1686895/is-there-an-equivalent-to-creating-a-c-sharp-implicit-operator-in-f – Adriano Repetti May 23 '12 at 12:25

3 Answers3

31

F# does not perform implicit conversions, but it allows you to define an explicit operator to run them. See the kvb's answer to a previous question:

let inline (!>) (x:^a) : ^b = ((^a or ^b) : (static member op_Implicit : ^a -> ^b) x) 

This is using statically resolved type parameters to say that either the input or the result needs to provide implicit conversion operator - these are compiled to methods named op_Implicit, so the F# compiler checks for a static method with this special name.

Using the !> operator, you can now explicitly say where you want to convert Parameter to a float (two times) in your code sample like this:

let a = Parameter(4.0) 
let b = Parameter(2.0) 
let c = !> a * Math.Sin(!> b)

I think the main reason for not allowing implicit conversions in F# is that it would make the type inference a bit more difficult and it would be hard for the compiler to give good error messages.

Community
  • 1
  • 1
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 3
    Hm, I can't decide which is uglier out of `A.Value * Math.Exp(time.Value) * Math.Sin(B.Value * time.Value)` and `!> A * Math.Exp(|> time) * Math.Sin(!> B * !> time)` – Benjol May 23 '12 at 12:46
  • @Benjol I fully agree - In fact, I'm pretty convinced that using `!>` operator is uglier than using `.Value` property, so I would probably just use that. The `!>` operator is probably only useful if you need to write other generic functions. – Tomas Petricek May 23 '12 at 12:52
  • What about if it is a C# generic, e.g.: `public static implicit operator MyClass(T t) => ...`. The actual implementation is irrelevant. The code above does not work and it fails with: `The declared type parameter T cannot be used here since the type parameter cannot be resolved at compile time`. – Konstantin Konstantinov Dec 29 '21 at 18:06
1

It won't let you do implicit conversions. Make your conversions explicit where you need to.

See here for various ways to do it explicitly: http://natehoellein.blogspot.com/2008/02/basic-type-conversions-with-f.html

jlew
  • 10,491
  • 1
  • 35
  • 58
  • Implicit operators aren't supported in general in F#. For instance the following doesn't compile: `let mutable a = 1.0 in a <- 2`. – Guvante May 24 '12 at 00:29
1

FSharp.Interop.Dynamic uses the DLR, so for most people probably overkill, but has a function Dyn.implicitConvert for dynamically using the C# implicit operator.

   [<Test>] member basic.``Test Implicit Conversion`` ()=
                    let ele = 50
                    ele |> Dyn.implicitConvert |> should equal (decimal 50)
jbtule
  • 31,383
  • 12
  • 95
  • 128