views:

111

answers:

3

I'm trying to make a struct in F# for representing depth curves in a sea map. It has to contain a list of coordinates and a float telling what depth is represented (eg. "4.5 meters"). I have made it this way:

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. )

My problem is that this doesn't let me create the Polygon and its Coords in one go, like this:

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

There do exist a solution for this:

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

but it doesn't let me have the depth-indicating float in the struct as well, and it doesn't let me restrict types of the list to be only Coords.

How do I combine the best from both worlds?

+1  A: 

The object types you created are standard .NET-structures with a constructor - They don't have the special F#-record-initialization sytnax ({ ... }).

For your problem, you could just write a little wrapper function:

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

used like this

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

When declaring your structures in the shortened record syntax, you should do it like this:

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. }

There is no reason why you should use a generic list, just specify Coord list (meaning List of Coords). And please note the difference between a list ([1; 2; 3]) and a tuple ((1, 2, 3)). The latter are much more suitable for representing coords.

Please take a look at this article on F# structures and types.

Dario
This is really nice. This lets me have the short notation and the cheese.
loldrup
...except it doesn't work in my VS 2008. See my full reply nicely formatted below
loldrup
The comma separating the coords and depth members in myCurve should be a semicolon.
kvb
A: 

The answer depends from the way you construct your program.

For case you activly use functional paradigm (no mutation, high-order functions, pattern matching) i vote for three choices:

(* 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 *)

for case you prefer OOP you can create simple object hierarchy.

The main advantage of FP is easy modification of your design at any step of program constraction. But of course, it cost to your by explicit state arguments. But may beat them by monadic expressions :)

ssp
I prefer functional programming :)I will look into your suggestions very shortly
loldrup
What worries about your functional solution is the lack of explicit types. Anything that looks like a curve goes.
loldrup
Not tagged tuples is not the best choice if you have many similar data structures, but you can use types and tagged unions :)
ssp
A: 

To Dario:

When I write this in VS 2008:

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

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

I get theese errors:

This expression has type  'a * 'b but is here used with type  Coord list
no assignment given for field 'depth'
loldrup
The comma separating the coords and depth members in myCurve should be a semicolon instead.
kvb