带记录的静态解析类型
您可能知道下面的适配器示例:
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
为 Cat 和 Dog 类静态编译不同版本的 walk。
然后我尝试了以下操作:
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
但出现以下编译错误:
The type 'Dog' does not support any operators named 'get_Name'
对于 Cat 类也是如此。
但是,当探索两条记录的生成类时,它实际上包含生成的 Name 属性的 get_Name 方法。
是否有不同的语法来访问静态解析泛型中的记录字段,或者这是 F# 编译器的限制?
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 ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
值得一提的是,记录类型可以实现接口。
你也可以做
It may be worth mentioning that record types can implement interfaces.
You can also do
您的
showName
函数实现适用于具有Name
属性的标准 .NET 类。尽管Cat
和Dog
都不是这样;相反,两者都是F#记录类型。尽管访问记录
字段
看起来与访问标准类属性
进行 F# 类型推断非常相似,但这两种情况是完全不同的。您定义了两种具有非唯一字段名称
Name
的记录类型;访问记录类型Cat
的实例cat
的字段Name
是cat.Name
,与类似狗
它是dog.Name
。但是,当您尝试showName cat
或showNamedog
时,编译器会抱怨这些记录类型中缺少Name
属性,这是预期的行为,因为有这些记录中没有此类财产。附录:
为了说明我的观点,我对原始代码做了一点修改,向
Cat
和Dog
添加属性Nickname
:这会很高兴地工作。
注意修改类的签名:现在是
最后,编译器将禁止同时使用类似于
命名的记录类型的字段和属性
无法定义成员“Xyzzy”,因为名称“Xyzzy” ' 与此类型或模块消息中的字段“Xyzzy”冲突。
Your
showName
function implementation applies to standard .NET classes havingName
property. Although neitherCat
norDog
are such; instead both are of F# record type.Despite accessing a record
field
looks literally similar to accessing a standard classproperty
for F# type inference these two cases are completely different.You have defined two record types with non-unique field name
Name
; access to the fieldName
of instancecat
of record typeCat
iscat.Name
, similarly fordog
it isdog.Name
. But when you tryshowName cat
orshowName dog
compiler complains on absense ofName
property 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
Nickname
to bothCat
andDog
: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 module
message.