views:

230

answers:

5

Hi

I'm very new to F# and I'm trying to make a struct for storing polygons, and it has to contain a list of coordinates:

type Polygon =
    struct
        val Coords : list
        new(list_of_Coords) = { Coords = list_of_Coords }
    end

but Visual studio says "The type 'Microsoft.FSharp.Collections.list<_>' expects 1 type argument(s) but is given 0"

I think not as I don't intend to initialise the list in the struct - just declare it.

+3  A: 

See

http://cs.hubfs.net/forums/thread/11377.aspx

for the answer.

(Repeated here:

You need to specify the type of list, e.g. list<float>.

type Polygon =
    struct
        val Coords : list<float>
        new(list_of_Coords) = { Coords = list_of_Coords }
    end

)

Brian
+4  A: 

In addition to Brian's anwer: You can also make the structure generic when you don't know the type of your coordinates in advance (even if string Polygon wouldn't make much sense)

type 'a Polygon =
    struct
        val Coords : 'a list
        new(list_of_Coords) = { Coords = list_of_Coords }
    end

Generally, you can declare a record type like this (assume you have a Coord type)

type Polygon = { Coords : Coord list }

// Code ...

let myPolygon = { Coords = [ ... ] }
Dario
Regarding the "let myPolygon = { Coords = [ ... ] }" syntax:Can I then enter something like this:"let myPolygon = { Coords = [ [1.,2.] , [3.,4.] ] }"or do I have to define all my Coords first? (I guess the latter as I failed doing the former)
loldrup
The structure is immutable, you'll have to specify all coords in the initialization => `let myPolygon = { Coords = [ (1., 2.); (3., 4.) ] }`
Dario
A: 

For case you want generate as float as int and other type polygons, you can use following code:

type Polygon<'a> =
    struct
        val Coords : list <'a>
        new(list_of_Coords) = { Coords = list_of_Coords }
    end

let inline genPolygon (a: 'a list) =
  new Polygon<'a> (a)

> genPolygon [1;2;3];;
val it : Polygon<int> = FSI_0002+Polygon`1[System.Int32] {Coords = [1; 2; 3];}
> genPolygon [1.0;2.0;3.0];;
val it : Polygon<float>
= FSI_0002+Polygon`1[System.Double] {Coords = [1.0; 2.0; 3.0];}
ssp
The effect of "let inline genPolygon (a: 'a list) = new Polygon<'a> (a)"is just to avoid having to use the constructor from the Polygon type directly?I'm more interested in being able to make a polygon without having to explicitly declare all it's corners first. I.e. write something like:let myPolygon = { Coords = [ [1.,2.] , [3.,4.] ] }
loldrup
Yes, i suppose, people prefer to use "genPoly [1;2;3]" over "new Polygon<int> [1;2;3]". It seems you want to use classic ML types, not structs. I don't know how to format comments, so please see next answer:
ssp
A: 

type 'a F = { coords: 'a list };;

type 'a F =
  {coords: 'a list;}

> let dd = {coords=[1.;2.]};;

val dd : float F

> let dd = {coords=[[1.;2.];[1.;2.]]};;

val dd : float list F
ssp
And if I want to ensure that polygons only use floats why can't I write this:type HeightCurve = { coords: list<float> };;let myHeightCurve = {coords=[[1.;2.];[1.;2.]]};;
loldrup
You can, of course. Just use "type HeightCurve = { coords: float list list}" for your case.
ssp
A: 

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 a problem combining all of theese features in the struct:

  1. The ability to have both the list of Coordinates and the float representing depth.
  2. The ability to limit the list-type to be coordinates (pairs of floats) and no other type than that.
  3. The ability to state my Coords inside the statement creating my polygon-instanses (like this: let myDepthCurve = {coords=[[1.;2.];[1.;2.]]};; )
  4. The ability to use inline notation

The first and the second point can be solved in tandem in this slightly verbose 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. )

Point three can be solved in this way

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

this brings me the short (and nice) Coord-definition but also the 'any type' string type, which I can't seem to alter to be stricly Coords. Also, I can't make the DepthCurve contain a depth-float as well, like this:

type 'a DepthCurve = {coords: 'a list; depth: float}
let myDepthCurve = {coords=[[1.;2.];[3.;4.]] , 5. };;

(this gives this error: "This expression has type 'b * 'c but is here used with type 'a list" and "no assignment given for field 'depth'")

Point 4 can be had this way:

type Coord  = { X : float; Y : float }
type DepthCurve<'a> =
    struct
        val Coords : list <'a>
        new(list_of_Coords) = { Coords = list_of_Coords }
    end

let inline genDepthCurve (a: 'a list) =
  new DepthCurve<'a> (a)

let myDepthCurve = genDepthCurve [1;2;3];;

but this brings the 'any type' list which I can't get rid off, and can't make coexist with my DepthCurve struct having anything else than this list.

Does anyone know how to combine them all?

loldrup