Ваша реализация функции showName
применяется к стандартным классам .NET, имеющим свойство Name
. Хотя ни Cat
, ни Dog
не являются таковыми; вместо этого оба типа F # record .
Несмотря на доступ к записи field
выглядит буквально для доступа к стандартному классу property
для вывода типа F #, эти два случая совершенно разные.
Вы определили два типа записей с неуникальным именем поля Name
; доступ к полю Name
экземпляра cat
типа записи Cat
равен cat.Name
, аналогично для dog
это dog.Name
. Но при попытке showName cat
или showName dog
компилятор жалуется на отсутствие свойства Name
в этих типах записей, что является ожидаемым поведением, поскольку в этих записях такого свойства нет.
Добавление:
Чтобы проиллюстрировать свою точку зрения, я сделал небольшое изменение в исходном коде, добавив свойство Nickname
к Cat
и Dog
:
type Cat = { Name : string } member x.Nickname = x.Name
type Dog = { Name : string } member x.Nickname = x.Name
let inline showName (animal : ^T ) =
let name = (^T : (member Nickname : string) (animal))
printfn "%s" name
let cat = { Name = "Miaou" } : Cat
let dog = { Name = "Waf" } : Dog
showName cat
showName dog
Это с радостью сработает.
Обратите внимание на сигнатуру модифицированных классов: теперь
type Cat =
{Name: string;}
with
member Nickname : string
end
И, наконец, компилятор запретит иметь как поле, так и свойство типа записи с аналогичным именем в сообщении The member 'Xyzzy' can not be defined because the name 'Xyzzy' clashes with the field 'Xyzzy' in this type or module
.