无法扩展F#中的运算符?

时间:2011-11-29 10:59:11

标签: f# operators extension-methods

module FSharp=
let Point2d (x,y)= Point2d(x,y)
let Point3d (x,y,z)= Point3d(x,y,z)
type NXOpen.Point3d with
    static member ( * ) (p:Point3d,t:float)= Point3d(p.X*t,p.Y*t,p.Z*t)
    static member ( * ) (t:float,p:Point3d)= Point3d(p.X*t,p.Y*t,p.Z*t)
    static member (+) (p:Point3d,t:float)= Point3d(p.X+t,p.Y+t,p.Z+t)
    static member (+) (t:float,p:Point3d)= Point3d(p.X+t,p.Y+t,p.Z+t)
    static member (+) (p:Point3d,t:Point3d)= Point3d(p.X+t.X,p.Y+t.Y,p.Z+t.Z)

let a=Point3d (1.,2.,3.)
let b=1.0
let c=a * b//error
  

错误15:类型'float'与类型
不匹配   'Point3d'E:\ Work \ extension-RW \ VS \ extension \ NXOpen.Extension.FSharp \ Module1.fs 18 13 NXOpen.Extension.FSharp

我想扩展Point3d方法,一些新的运算符。但它并没有过去。

2 个答案:

答案 0 :(得分:5)

如果Point3d类型在一个你无法修改的单独程序集中声明,那么(遗憾的是)没有办法实现标准运算符的新重载,如+或{{1 }}。您的问题中的代码将运算符添加为扩展方法,但F#编译器在查找重载运算符时不会搜索扩展方法。

如果您无法修改库,那么您可以执行以下三项操作:

  • *创建一个包装器,它存储值Point3d并实现所有操作员
    (但这可能效率很低)

  • 定义不与内置运算符冲突的新运算符。例如,您可以使用Point3d+$从左侧和右侧按标量进行乘法运算。要声明这样的运算符,您可以写:

    $+
  • 实施您自己的let (+$) (f:float) (a:Point3d) = (...) 类型,可以完成所有工作,可能还有一个转换函数,可以在需要调用库时将其转换为Point3d

很难说哪个选项最好 - 第二种方法可能效率最高,但它会让代码看起来更加丑陋。根据您的情况,选项1或3也可能有效。

答案 1 :(得分:3)

确实有可能。 有一种方法可以使用one和only little known ternary operator ?<-扩展二元运算符。所以在你的情况下你可以试试这个:

type SumPoint3d = SumPoint3d with
    static member        (?<-) (p:Point3d, SumPoint3d, t        ) = Point3d(p.X + t  , p.Y + t  , p.Z + t  )
    static member        (?<-) (t        , SumPoint3d, p:Point3d) = Point3d(p.X + t  , p.Y + t  , p.Z + t  )
    static member        (?<-) (p:Point3d, SumPoint3d, t:Point3d) = Point3d(p.X + t.X, p.Y + t.Y, p.Z + t.Z)
    static member inline (?<-) (a        , SumPoint3d, b        ) = a + b

type ProdPoint3d = ProdPoint3d with    
    static member        (?<-) (p:Point3d, ProdPoint3d, t        ) = Point3d(p.X * t, p.Y * t, p.Z * t)
    static member        (?<-) (t        , ProdPoint3d, p:Point3d) = Point3d(p.X * t, p.Y * t, p.Z * t)
    static member inline (?<-) (a        , ProdPoint3d, b        ) = a * b

let inline ( + ) a b =  a ? (SumPoint3d ) <- b
let inline ( * ) a b =  a ? (ProdPoint3d) <- b

let a=Point3d (1.,2.,3.) 
let b=1.0

现在你可以尝试:

> let c=a * b ;;
val c : Point3d = Point3d (1.0,2.0,3.0)

>  2 * 3 ;;
val it : int = 6