在非泛型 F# 接口中创建和使用泛型函数
目前这超出了我的范围。我正在尝试创建一个看起来像这样的界面 这。
type IFetchData =
abstract FetchData: string -> seq<'a>
上面的声明是有效的(并且可以编译),但是当我使用它时,我收到编译时错误。该表达式的预期类型为“a”,但这里的类型为“我当前尝试返回的内容”,即 seq。
然而,我的示例用法如下所示:
type SampleFetchData() =
interface IFetchData with
member self.FetchData str =
seq {
for letter in str do
yield letter // compile error here
}
我不确定我做错了什么。我想做的就是允许接口实现者能够编写返回通用序列的任何函数 seq
,seq
,< code>seq<此处的记录类型>、seq<此处的联合类型>
等。
有人可以告诉我这里缺少什么吗?
谢谢。
It is beyond me at this point. I'm trying to create an interface that looks something like
this.
type IFetchData =
abstract FetchData: string -> seq<'a>
The above declaration is valid (and compiles) but when I go to use it I get a compile time error. This expression was expected to have type 'a but here has type "what I'm currently trying to return" i.e. seq.
My example usage however looks like the following:
type SampleFetchData() =
interface IFetchData with
member self.FetchData str =
seq {
for letter in str do
yield letter // compile error here
}
I'm not sure what I'm doing wrong. All I'd like to do is allow the interface implementer to be able to write any function that returns a generic sequence either seq<string>
,seq<int>
,seq<record type here>
, seq<union type here>
, etc.
Can someone tell me what I'm missing here?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您使用反射加载接口实现,那么使用它将会非常困难。问题是你得到了一个为该类型。
obj
类型的对象。您知道它为某些'T
实现了IFetchData<'T>
,但静态地,您不知道为哪个'T
。这是一个问题,因为您无法将对象强制转换为任何更具体的类型 - 如果您尝试使用IFetchData
,它将不起作用,因为您无法强制转换,例如 < code>IFetchData我建议使用非通用接口,这是非常常见的 .NET 模式:
当您使用 Reflection 加载实现时,您可以将对象强制转换为 IFetchDataUntyped 并以相当合理的方式使用它(使用
Seq.cast
将序列转换为更具体的类型(如果您知道元素类型)。根据您的应用程序,您还可以将
FetchData
方法设置为通用方法,并保持接口非通用。然后,您可以将动态加载的对象强制转换为接口并调用该方法。然而,这改变了设计(因为该方法必须适用于它作为类型参数获取的任何类型):If you're loading the interface implementation using Reflection, then it is going to be quite difficult to work with it. The problem is that you get an object of type
obj
. You know that it implementsIFetchData<'T>
for some'T
, but statically, you don't know for which'T
. This is a problem because you can't cast the object to any more specific type - if you tried usingIFetchData<obj>
, it wouldn't work because you can't cast, for example,IFetchData<int>
to that type.I would recommend using a non-generic interface, which is quite common .NET pattern:
When you load an implementation using Reflection, you can cast the object to
IFetchDataUntyped
and work with it in a fairly reasonable way (usingSeq.cast
to convert the sequence to a more specific type if you know the element type).Depending on your application, you may also just make the
FetchData
method a generic method and keep the interface non-generic. Then you could cast dynamically loaded objects to the interface and invoke the method. However, this changes the design (because the method has to work for any type it gets as a type parameter):您需要做类似的事情
,即接口需要变得通用。如果您想避免通用性,您可以使用一些内联约束,而不是接口
编辑:内联魔术版本
You need to do something like
i.e. the interface needs to be made generic. If you want to avoid the genericness you could use some inline constraints, rather than an interface
EDIT: Inline magic version