If you use classes, you can have overloading. I'm not sure if it's what you need:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 

type Conv =
  [<OverloadID("2")>]
  static member TupleToArray t =
    let e1, e2 = t in [|box e1; box e2|]

  [<OverloadID("3")>]
  static member TupleToArray t =
    let e1, e2, e3 = t in [|box e1; box e2; box e3|]
  // add more

  [<OverloadID("2")>]
  static member ArrayToTuple (a: _ array) =
    unbox a.[0], unbox a.[1]

  [<OverloadID("3")>]
  static member ArrayToTuple (a: _ array) =
    unbox a.[0], unbox a.[1], unbox a.[2]
  // add more

let a = 1, "a"
let b = Conv.TupleToArray a
let c : int * string = Conv.ArrayToTuple b

c;;
val it : int * string = (1, "a")

Laurent.

By on 4/22/2008 6:33 AM ()

I'm not sure, but it strikes me as unusual to store several values of identical type in a tuple. Can you describe what your original design goal was? Maybe instead of using tuples, use lists?

Going between lists and arrays would be easy:

1
2
3
4
let list1 = [1; 2; 3]
let array1 = List.to_array list1
let array2 = [|1; 2; 3; 4|]
let list2 = List.of_array array2
By on 4/21/2008 1:21 AM ()

There isn't an overall design in this case---for me it's more a question of how to use the primitives available. As you know, tuples are a natural way to bind different types together to represent something. For instance, a relation's row might be represented by a tuple to maintain the types of the columns. A problem arises if one is working with legacy systems though; you have to be able to translate to/from the natural F# representation to something common.

The code I originally posted does this for me, but it is unsafe in that you can put anything in for the generic argument. It would be nice if there were an expressible type constraint so that only tuples would satisfy the definition. Currently, if I put a float in, I get the unexpected behavior (for me) of an empty array out. (I would have liked to have seen at least a runtime error!)

Given the definition of Tuple, I was pretty sure a type constraint didn't exist, but I was hopeful. :)

By on 4/21/2008 6:56 AM ()

If you know the number of items in the tuple, why not use something like this ?

1
2
3
4
5
6
7
8
 

let arrayToTuple (arr: obj[]) : ('a * 'a) =
  let f = Reflection.Value.GetTupleConstructor (typeof<'a * 'a>)
  (f arr) :?> ('a * 'a)

let x : (int * int) = (5, 6) |> tupleToArray |> arrayToTuple ;;
By on 4/21/2008 9:59 AM ()

The point was to create one function that accepts tuple types of any arity but not any other types.

By on 4/21/2008 10:12 AM ()

The following code doesn't work in todays F#, but it might in a future version of F#:

type ('a * 'b) with
static member TupleToArray (a: 'a, b: 'b) = [|box a; box b|]

type ('a * 'b * 'c) with
static member TupleToArray (a: 'a, b: 'b, c: 'c) = [|box a; box b; box c|]

(* ... augment more tuple types ... *)

let inline tupleToArray (tuple: ^a) : obj[] =
(^a : (static member TupleToArray : ^a -> obj[]) (tuple))

This doesn't work for two reasons: a) you can't extend tuple types and b) the compiler ignores members provided through type extensions when resolving member constraints for inline functions. I wonder what the future language specification will say about this...

If member constraints for inline functions worked with members provided through type extensions you could do some really cool stuff.

By on 4/21/2008 8:38 AM ()

No it's no possible, tuples of different arity are different types with no common base class. Although this may seem kind of illogical at first, I don't think it is. Tuples of arity type have very little in common, the only thing a tuple of 2 items and a tuple of three items have in common is that you can access the first two items, and even here the since is different since you must always account for all items in a tuple when breaking it up:

1
2
3
4
// breaking up a tuple of two
let fst,snd = t2
// breaking up a tuple of three
let fst,snd,thrd = t3
By on 4/21/2008 2:22 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper