我可以在F#中避免这种演员吗?

时间:2018-05-24 13:48:08

标签: f#

这个问题的背景是我正在写的光线跟踪器。

我有一个Surface类型,理想情况下我希望它是NoSurface和Lambertian继承的抽象基类。

但是当我有这个层次结构时,我遇到以下问题:

    let closestIntersection : bool*LineParameter*Surface = 
    match allIntersectionsWithRealSolutions with 
        | [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)))
        | x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions

这会抛出编译器错误,因为它将返回类型绑定到的类型是NoSurface,即使将类型指定为Surface也是如此。

这解决了这个问题:

    let closestIntersection : bool*LineParameter*Surface = 
    match allIntersectionsWithRealSolutions with 
        | [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)) :> Surface)
        | x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions
closestIntersection

但根据BenchmarkDotNet,演员:>花了我25ms,相比之下,将Surface定义为(非抽象)类而只是简单地返回它的解决方案!

我可以以某种方式避免显式转换并具有所需的Surface is和抽象类层次结构吗?

1 个答案:

答案 0 :(得分:3)

您可以尝试使用有区别的联盟解决同样的问题,这将是更具功能性的联盟。因为你正在使用F#?虽然我有点确定这种方法可能会慢一些。但是,如果您在最高性能之后,托管语言不是最好的选择。 在https://fsharpforfunandprofit.com/posts/discriminated-unions/

找到一个好的工会解释

这样的事情。

type Intersectable =
    | Sphere of center:Point3 * radius:float
    | Triangle of v0:Point3 * v1:Point3 * v2:Point3
    | MeshTriangle of faceIndex:int * mesh:Mesh
    | Instance of Intersectable * Matrix.Matrix4x4
    | Plane of normal:Vec3 * pointOnPlane: Point3

共享/通用功能可以通过使用您的功能所依据的通用数据部分来解决,您可能拥有:

type Shape = {
    geometry: Intersectable
    material: Material }
相关问题