简体   繁体   中英

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)

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM