[英]f# member constraints and IEnumerable collections
我是F#的新手,今天我看到了F#的成员约束功能。
我在考虑是否可以以下方式使用它...
说我想迭代获取ListView中的项目的文本。 我可以这样做:
let listView = new System.Windows.Forms.ListView()
let itemTexts =
listView.Items
|> Seq.cast<System.Windows.Forms.ListViewItem>
|> Seq.map (fun item -> item.Text)
上面的Seq.cast类型不安全且难看。
我当时在想的是:
> let item (i:int) = listView.Items.Item i;;
val item : int -> System.Windows.Forms.ListViewItem
因此IEnumerable
的类型实际上是以一种循环方式编码到该类中的。
我看到的成员约束示例如下:
type Cat() =
member this.Walk() = printfn "cat walk"
type Dog() =
member this.Walk() = printfn "dog walk"
let adapter() =
let cat = Cat()
let dog = Dog()
let inline walk (x : ^T) = (^T : (member Walk : unit->unit) (x))
walk(cat)
walk(dog)
我的想法是,它与我上面想要做的有点类似。
可以使用它来创建一个如下所示使用的函数吗?
let itemTexts =
listView.Items
|> Seq.asSeq
|> Seq.map (fun item -> item.Text)
编辑 :当时的想法是实现一个通用Seq.asSeq
那会拿东西,实现了非泛型扩展方法IEnumerable
并具有强类型的Item
-member如上,然后调用Seq.cast
从相应类型Item
-会员。
这是我的第一次摸索尝试:
let listView = new System.Windows.Forms.ListView()
let items =
listView.Items
type cat() =
member this.Item (i:int) = "cat walk"
interface System.Collections.IEnumerable with
member this.GetEnumerator() = ((seq { yield (this.Item 0) }) :> System.Collections.IEnumerable).GetEnumerator()
type dog() =
member this.Item (i:int) = 6
interface System.Collections.IEnumerable with
member this.GetEnumerator() = ((seq { yield (this.Item 0) }) :> System.Collections.IEnumerable).GetEnumerator()
let cat = cat()
let dog = dog()
let inline asSeq (x : ^t) =
let dummy _ = (^t : (member Item : int -> 'a) (x, 0))
Seq.cast<'a> x
这几乎可以工作,但不适用于实际类型!
> cat;;
val it : cat = seq ["cat walk"]
> asSeq cat;;
val it : seq<string> = seq ["cat walk"]
> asSeq dog;;
val it : seq<int> = seq [6]
> asSeq items;;
asSeq items;;
------^^^^^
C:\...\stdin(5,7): error FS0001: The type 'System.Windows.Forms.ListView.ListViewItemCollection' does not support any operators named 'Item'
>
我猜这是我的假类型无法正确反映.NET索引属性...
有什么帮助吗?
编辑2:这实际上有效!
let inline asSeq (x : ^t) =
let dummy _ = (^t : (member Item : int -> 'a with get) (x, 0))
Seq.cast<'a> x
听起来您需要这些方面的东西,在这种情况下,您的代码几乎是正确的。
请注意,一个问题是您试图与方法互换使用索引属性,但您做得并不正确:对于名为Item
的索引属性,该方法的实际名称将为get_Item
(或者,您可以使用语法member Item : int -> 'a with get
而不是直接使用get_Item
方法)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.