Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Records: Fields With Identical Names

Tags:

f#

Please consider the following record definitions:

type A = { F1 : int; F2 : int }
type B = { F1 : int; F3 : int } 

// error FS0656: This record contains fields from inconsistent types   
let a1 = { F1 = 1; F2 = 2 } 

// this works
let a2 = { A.F1 = 1; F2 = 2 }

I don't understand, why a1 results in an error.

All the examples I could find of why you have to do it the a2-way assume that all the field-names in A and B have the same name - which is of course ambiguous, but shouldn't A and B be distinguishable when having at least one distinct field?

Maybe this ist just the way F# evaluates this and adding the type name to the first field is of course no big deal, but I'm just curious.

EDIT: Thanks for the answers which helped me notice something rather strange: The whole snippet works, when I evaluate it the first time (ALT+Enter in VS 2010).

When I try to evaluate a second time, I get the error.

If nobody can reproduce this my installation of VS is probably borked...

EDIT2 (alright, time to create an account here, sorry for the edits) Thanks wmeyer (and everyone else) for taking the time to look at the problem and making me aware of my misunderstanding how FSI works. All cleared up now!

like image 834
knotig Avatar asked Mar 08 '11 10:03

knotig


3 Answers

I don't think your installation is borked.

It makes sense that the code does not work when evaluated the second time. The old types A and B still exist, they are just shadowed.
Field names, on the other hand, are never shadowed. (Otherwise you could never have the same field name in two different records.)
The "union of all possible records" (see Massif's answer) has more than one element now: the old (shadowed) A and the new A.

To solve this problem, you could use "Reset session" from the F# Interactive context menu in between runs. Or wrap your code in a module (then the old record types will be neither accessible nor in scope).

like image 178
wmeyer Avatar answered Nov 16 '22 07:11

wmeyer


just checked with fsi, this code works

type A = { F1 : int; F2 : int }
type B = { F1 : int; F3 : int } 
let a1 = { F1 = 1; F2 = 2 } 

maybe you have something else that wasn't mentioned in your post that causes this ambiguity?

like image 5
desco Avatar answered Nov 16 '22 08:11

desco


Indeed, it does sound like it should work - from the spec:

If field-labeli is not a single identifier or the initial type is a variable type, then the field label is resolved by performing Field Label Resolution (see §14.1) on field-labeli, which results in a set of fields FSeti. Each element of this set has a corresponding record type, resulting in a set of record types RSeti. The intersection of all RSeti must give a single record type R, and each field then resolves to the corresponding field in R.

Which implies as long as the union of all the possible records that contain those field identifiers resolves down to just one record type, then it's legal. What compiler are you using?

like image 3
Massif Avatar answered Nov 16 '22 08:11

Massif