0

我正在尝试在 F# 中创建一个结构来表示海图中的深度曲线。它必须包含一个坐标列表和一个指示深度的浮点数(例如“4.5 米”)。我是这样做的:

type Coord =
    struct
        val X : float
        val Y : float
        new(x,y) = { X = x ; Y = y }
    end

type DepthCurve =
    struct
        val Coords : list<Coord>
        val Depth  : float
        new(list_of_Coords, depth) = { Coords = list_of_Coords ; Depth = depth}
    end

let myCoord1 = new Coord(1.,2.)
let myCoord2 = new Coord(3.,4.)
let myDepthCurve = new DepthCurve([myCoord1;myCoord2] , 5. )

我的问题是,这不允许我一次性创建多边形及其坐标,如下所示:

let myDepthCurve = {coords=[[1.;2.];[3.;4.]] , 5}

确实存在一个解决方案:

type Coord  = { X : float; Y : float }
type 'a DepthCurve = {coords: 'a list;}
let myDepthCurve = {coords=[[1.;2.];[3.;4.]]};;

但它也不能让我在结构中拥有指示深度的浮点数,也不能让我将列表的类型限制为只有 Coords。

我如何结合两全其美?

4

2 回答 2

1

您创建的对象类型是带有构造函数的标准 .NET 结构 - 它们没有特殊的 F#-record-initialization sytnax ( { ... })。

对于您的问题,您可以只编写一个小包装函数:

let curve depth coords = New DepthCurve([for (x, y) in coords -> New Coord(x, y)], depth)

像这样使用

let testCurve = curve 10. [(1., 2.); (3., 4.); ...]

当用缩短的记录语法声明你的结构时,你应该这样做:

type Coord = float * float // Type-alias for a 2D-float-tuple
type DepthCurve = { coords : Coord list; depth : float }

let myCurve = { coords = [(1., 2.); ...], depth = 42. }

没有理由使用通用列表,只需指定Coord list(含义List of Coords)。[1; 2; 3]请注意列表 ( ) 和元组 ( )之间的区别(1, 2, 3)。后者更适合表示坐标。

请查看这篇关于 F# 结构和类型的文章。

于 2009-07-24T10:47:16.327 回答
0

答案取决于您构建程序的方式。

如果您积极使用功能范式(无突变、高阶函数、模式匹配),我投票支持三个选项:

(* tuple with type constractor and any getters you need: *)
let makeCoord x y = (x,y)
let makeCurve depth coords = (depth,coords)
let addCurveCoord (depth,coords) coord = (depth, coord::coords)
let getCurveDepth (depth,_) = depth
let getCurveCoords (_,coords) = coords
let getFirstCurveCoord (_,coords) = List.hd coords
//...

(* or types described by Dario *)
(* or tagged unions for case you need specific access to parts of your data *)

如果您更喜欢 OOP,您可以创建简单的对象层次结构。

FP 的主要优点是在程序构建的任何步骤都可以轻松修改您的设计。但是,当然,通过显式的状态参数会花费您的成本。但可能会用一元表达式击败他们:)

于 2009-07-24T13:27:52.317 回答