Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# member constraints on tuples

I commonly have a "oh yeah" moment writing F# when I realize I need an extra value somewhere. This is generally easily done by adding another value to the tuple being passed around. However, this means that various maps/sorts/collects/etc. need updating, and in particular the functions fst/snd only work on tuples of length 2.

It's not a huge issue, but it's annoying enough during exploratory development that I though I'd write a helper to alleviate the annoyance:

let inline get2 (t:^a) = (^a : (member get_Item2 : unit -> string) (t, ()))
let inline get2a (t:^a) = (^a : (member Item2 : string) t)

However, both versions do not work. The first, get2, won't compile, with "Expected 1 expressions, got 2". The second, get2a, will compile, but subsequently can't be used on tuples: "The type '(int * string)' does not support any operators named 'get_Item2'".

Is there any way of doing this that doesn't involve lots of overloads? with noisy OverloadID annotations (annotations not required in F# 2.0)

like image 656
Eamon Nerbonne Avatar asked Dec 21 '22 10:12

Eamon Nerbonne


2 Answers

The reason why ItemX static constraints on F# tuples do not work is because System.Tuple<_,...,_> is only the encoded form of tuples, and not the static representation used by the compiler. See 6.3.2 Tuple Expressions in the specification.

However, with a little work, you can obtain the runtime encoding of a given tuple like so:

open System
//like get2a but generic return type
let inline get2b (t:^a) = (^a : (member Item2 : 'b) t)

let x = (1,2)
let y = (1,2,3)

get2b (box x :?> Tuple<int,int>)
get2b (box y :?> Tuple<int,int,int>)
like image 124
Stephen Swensen Avatar answered Dec 25 '22 23:12

Stephen Swensen


You can do it using reflection:

let inline get (t:^a) = t.GetType().GetProperty("Item2").GetValue(t,null) :?> string

Also, I would suggest that tuples are not really a great data structure for passing data around, they may be useful inside a function for small operations, but in case there is a frequent change in the structure, tuple can be really painful to work with

like image 42
Ankur Avatar answered Dec 26 '22 00:12

Ankur