是否可能要求静态解析的类型参数为泛型?

时间:2019-06-21 06:16:55

标签: f#

具有层次结构

open FSharp.Data.UnitSystems.SI.UnitSymbols

type Vector2D<[<Measure>] 'u>(x: float<'u>, y: float<'u>) =
   member val Abs = 
     let squared = float (x*x+y*y)
     LanguagePrimitives.FloatWithMeasure<'u> (Math.Sqrt squared)      

type R2D = 
    inherit Vector2D<m>(x, y)
    member val X = x
    member val Y = y

type V2D(vx, vy) = 
    inherit Vector2D<m/s>(vx, vy)
    member val Vx = vx
    member val Vy = vy       

type A2D(ax, ay) =
    inherit Vector2D<m/s^2>(ax, ay)
    member val Ax = ax
    member val Ay = ay

我想定义全局内联运算符(+) (l:^v) (r:^v),其中需要^vVector2D继承,具有度量单位float<'u>,并且具有构造函数带有两个float<'u> 类型的参数。

有可能吗?

2 个答案:

答案 0 :(得分:4)

您可以尝试定义add函数,然后将其分配给infix运算符:

let add<[<Measure>]'u, 'v when 'v :> Vector2D<'u>> (l:^v) (r:^v) = l.Abs + r.Abs

let (+) left right = add left right

已编辑: 这是您可以使用的方式: 在这种情况下,左右类型必须匹配

let left = R2D(1.0<m>,1.0<m>)
let right = R2D(2.0<m>,2.0<m>)
let result = left + right

或者您可以尝试不使用匹配类型,但仍然必须匹配

let left:Vector2D<m> = R2D(1.0<m>,1.0<m>) :> Vector2D<m>
let right:Vector2D<m> = A2D2(2.0<m>,2.0<m>) :> Vector2D<m>
let result = left + right

答案 1 :(得分:2)

您可以为+的每个子类型定义一个单独的Vector2D,如下所示:

type V2D(vx, vy) = 
    inherit Vector2D<m/s>(vx, vy)
    member val Vx = vx
    member val Vy = vy
    static member (+) (l:V2D, r:V2D) = V2D(l.Vx + r.Vx, l.Vy + r.Vy)

type A2D(ax, ay) =
    inherit Vector2D<m/s^2>(ax, ay)
    member val Ax = ax
    member val Ay = ay
    static member (+) (l:A2D, r:A2D) = A2D(l.Ax + r.Ax, l.Ay + r.Ay)

let v1 = V2D(2.0<m/s>, 3.0<m/s>)
let v2 = V2D(2.0<m/s>, 3.0<m/s>)
v1 + v2 //yields in FSI: val it : V2D = FSI_0002+V2D {Abs = 7.211102551; Vx = 4.0; Vy = 6.0;}

如果您还想提高性能,也可以inline,如果不想处理多态和/或类型检查,可以用相同的方式定义其他数学函数。