You probably know the Adapter example below :
type Cat() =
member this.Walk() = printf "Cat walking"
type Dog() =
member this.Walk() = printf "Dog walking"
let inline walk (animal : ^T ) =
(^T : (member Walk : unit -> unit) (animal))
let cat = new Cat()
let dog = new Dog()
walk cat
walk dog
a different version of walk is compiled statically for the Cat and Dog classes.
Then I tried the following :
type Cat = { Name : string }
type Dog = { Name : string }
let inline showName (animal : ^T ) =
let name = (^T : (member Name : string) (animal))
printf "%s" name
let cat = { Name = "Miaou" } : Cat
let dog = { Name = "Waf" } : Dog
showName cat
showName dog
but I get the following compilation error :
The type 'Dog' does not support any operators named 'get_Name'
and the same for class Cat.
But when exploring the generated class for both records, it actually contains this get_Name method for the generated Name property.
Is there a different syntax to access Records fields in statically resolved generics, or is it a F# compiler limitation ?
Your
showNamefunction implementation applies to standard .NET classes havingNameproperty. Although neitherCatnorDogare such; instead both are of F# record type.Despite accessing a record
fieldlooks literally similar to accessing a standard classpropertyfor F# type inference these two cases are completely different.You have defined two record types with non-unique field name
Name; access to the fieldNameof instancecatof record typeCatiscat.Name, similarly fordogit isdog.Name. But when you tryshowName catorshowName dogcompiler complains on absense ofNameproperty in these record types, which is expected behavior, because there is no such property in these records.Addendum:
To illustrate my point I did a slight modification to the original code adding property
Nicknameto bothCatandDog:This will happily work.
Take a notice of signature of modified classes: it is now
And finally, the compiler will forbid having both a field and a property of a record type similarly named with
The member 'Xyzzy' can not be defined because the name 'Xyzzy' clashes with the field 'Xyzzy' in this type or modulemessage.