gpt4 book ai didi

generics - f# 成员约束和 IEnumerable 集合

转载 作者:行者123 更新时间:2023-12-04 04:32:22 26 4
gpt4 key购买 nike

我是 F# 的新手,今天我看到了 F# 的成员约束功能。

我在想是否可以(ab)以下列方式使用它......

假设我想迭代获取 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 的相应类型-成员(member)。

这是我的第一次摸索:
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'
>

我想这是我的假类型没有正确反射(reflect) .NET 索引属性......

有什么帮助吗?

编辑 2:这确实有效!
let inline asSeq (x : ^t) =
let dummy _ = (^t : (member Item : int -> 'a with get) (x, 0))
Seq.cast<'a> x

最佳答案

听起来你想要一些东西 these lines ,在这种情况下,您的代码几乎是正确的。

请注意,一个问题是您试图将索引属性与方法互换使用,但您做得并不完全正确:对于名为 Item 的索引属性。 ,该方法的实际名称将为 get_Item (或者,您可以使用语法 member Item : int -> 'a with get 而不是直接使用 get_Item 方法)。

关于generics - f# 成员约束和 IEnumerable 集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20375646/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com