4

For example, I define a record as:

type a = {b : float; c: int list}

but I already know that this list must be of a predefined size, let's say 2 and if the list is not 2 it would be a different type or error since it is not defined such a type.

Is it possible to define the size of the list as happens in other languages that you must define the size? Depending on the application this question can be applied to an array.

Jose M Gonzalez
  • 349
  • 3
  • 16
  • 8
    Just because different languages use the same name for a type does not mean they are the same. Right now I am translating Python to F# and I can assure you a Python list is not the same as an F# list or a C# list. If you are trying to translate a type from one language to another concentrate on how the type functions and not the name of the type. Why don't you use a tuple? – Guy Coder Jan 15 '16 at 15:33
  • 1
    You can check when an object is created. – FoggyFinder Jan 15 '16 at 15:36
  • 1
    Do you need compile time type checking or run time type checking? – Guy Coder Jan 15 '16 at 15:40
  • @GuyCoder , it's true what you say, and just know I don't remember, also in Python the size of a list is not fixed. The point of using a a tuple with **int*int** would save the case, but the access to one element of a tuple in F# if I'm not wrong there are the _fst_ and _scn_ methods but not more (probably one for the last, but I don't remember). Should be run time checking – Jose M Gonzalez Jan 15 '16 at 15:51
  • Why run time checking over compile time checking. Run time checking means that you will use more time during running to perform the check while compile time checking means that the check is done once during the compile which then means you are not extending the run time. – Guy Coder Jan 15 '16 at 16:13
  • While F# gives you a few functions to decompose a tuple you can create as many as you need. e.g. (a,b) = (1,2) | for three values (a,b,c) = (1,2,3) | for four values (a,b,c,d) = (1,2,3,4) etc. See: [Feeding tuple into function such as printfn](http://stackoverflow.com/q/20568309/1243762) for more ideas. – Guy Coder Jan 15 '16 at 16:16
  • F# doesn't support type-level naturals, so I don't think it's possible to do this statically. – Lee Jan 15 '16 at 16:22
  • While I did ask about using a Tuple don't take that to mean that is what I am suggesting. You gave very limited information and that was just the best idea based on it. You could also create a new type, use a [Array2D](https://msdn.microsoft.com/en-us/library/ee353794.aspx), create a [record](https://msdn.microsoft.com/en-us/library/dd233184.aspx), etc. Take some time and look at all the types of data structures F# has to offer and how to crate new types without your problem in mind. Then come back to your problem with a better set of constructs and means to solve your problem. – Guy Coder Jan 15 '16 at 16:25
  • Are you looking for the `ResizeArray`? https://msdn.microsoft.com/en-us/library/ee353447.aspx – N_A Jan 15 '16 at 16:26
  • 1
    Possible duplicate of [No F# generics with constant "template arguments"?](http://stackoverflow.com/questions/32602760/no-f-generics-with-constant-template-arguments) – Mark Seemann Jan 15 '16 at 16:26
  • @Lee Where did type-level naturals come from with regards to this question? – Guy Coder Jan 15 '16 at 16:30
  • 1
    @GuyCoder - OP appears to want the length of the list to be part of the type, so a list with two elements would have type `List 2 T`. – Lee Jan 15 '16 at 16:41
  • @GuyCoder Dependent types would let you parametrise a collection with a size but then there are very few general purpose languages that support that. Idris, for example, has a `Vector` type with statically typed length. In F#, I think, assuming that the number of elements is very small (e.g. 2), your first suggestion of using a tuple (or equivalent) is probably best. – TheInnerLight Jan 15 '16 at 16:46
  • @Lee I can see your point. Hopefully the OP will clarify his question so someone can give a reasonable answer. – Guy Coder Jan 15 '16 at 17:19
  • @Jose Use tuples. [How to get an arbitrary member of a tuple by index](http://stackoverflow.com/q/5252628/1046207). – Esoteric Screen Name Jan 15 '16 at 19:05
  • @Lee and GuyCoder yes, this was the idea as it's on the answer.Thank you very much for your comments. – Jose M Gonzalez Jan 18 '16 at 08:46

1 Answers1

4

Maybe you should use an array instead of a list, since an array has a fixed length:

// create an array of length = 2, initialized with zeros.
let cValues : int[] = Array.create 2 0
cValues.IsFixedSize // returns true

EDIT: As others have suggested, a tuple might also be the way to go. For a pair (a tuple of length two), you can access the values using the fst and snd functions. For a longer tuple, you can use pattern matching as shown below. If the tuple is too long to make this pattern matching approach practical, then you probably need a structure other than an F# tuple. Of course, one major requirement to consider is whether you need to store values of mixed types. A tuple or a record can store a mix of multiple types, whereas an array or list stores values of a single type.

let fourTuple = (5, 10, 2, 3)
let _,_,third,_ = fourTuple
printfn "%d" third // displays "2"

If an array or a tuple won't meet your requirements, then maybe you should use another record like this:

type ListOfC = {c1 : int; c2 : int}
type a' = {b' : float; c' : ListOfC}

Or you could create a new class that would meet your requirements, starting like the script below. Of course, this would probably not be considered idiomatic functional programming style. It's more like OOP.

type ListOfTwo(firstInt : int, secondInt : int) =
    member this.First = firstInt
    member this.Second = secondInt

let myListOfTwo = ListOfTwo(4, 5)
myListOfTwo.First

type a = {b : float; c : ListOfTwo }
Scott Hutchinson
  • 1,703
  • 12
  • 22
  • 2
    Just because tuples were covered in comments does not mean you should not include it in your answer. Most people using this Q&A will probably get here from a Google search and spend maybe one minute looking at the Question and accepted answer and move on. They typically skip the comments. Don't look at this as answering just for the OP, but anyone who comes here. Take a look at [Tomas's answers](http://stackoverflow.com/users/33518/tomas-petricek?tab=answers) for quality answers. – Guy Coder Jan 15 '16 at 19:54