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方法,一些新的运算符。但它并没有过去。
答案 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