无论如何使用F#的C#隐式运算符?

Ben*_*jol 12 c# f# implicit-conversion

如果我有一个C#类隐式转换为double,如下所示:

public class Parameter
{
    private double _value;
    public Parameter(double value) { _value = value }
    public static implicit operator double(Parameter p) { return _value; }
}
Run Code Online (Sandbox Code Playgroud)

F#不喜欢我试图使用它,就好像它是float:

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

有没有办法做到这一点(我猜不会,基于这个问题/答案),如果没有,什么是一个体面的解决方法?

Tom*_*cek 21

F#不执行隐式转换,但它允许您定义一个显式运算符来运行它们.请参阅kvb对上一个问题的回答:

let inline (!>) (x:^a) : ^b = ((^a or ^b) : (static member op_Implicit : ^a -> ^b) x) 
Run Code Online (Sandbox Code Playgroud)

这是使用静态解析的类型参数来表示输入或结果需要提供隐式转换运算符 - 这些运算符被编译为命名的方法op_Implicit,因此F#编译器检查具有此特殊名称的静态方法.

使用!>运算符,您现在可以在代码示例中明确说出要转换Parameterfloat(两次)的位置,如下所示:

let a = Parameter(4.0) 
let b = Parameter(2.0) 
let c = !> a * Math.Sin(!> b)
Run Code Online (Sandbox Code Playgroud)

我认为不允许在F#中进行隐式转换的主要原因是它会使类型推断变得更加困难,并且编译器很难给出好的错误消息.

  • 嗯,我无法确定`A.Value * Math.Exp(time.Value)* Math.Sin(B.Value * time.Value)`和`!&gt; A * Math.Exp(| &gt;时间)* Math.Sin(!&gt; B *!&gt;时间)` (2认同)