Interface 使用泛型lambda处理接口集合的方法

Interface 使用泛型lambda处理接口集合的方法,interface,f#,Interface,F#,我目前正在尝试使用F#进行试验,我正在努力解决如何最好地处理以下类型的场景: [<Interface>] type IStuff<'a> = abstract member Update: 'a -> 'a type Stuff1<'a> = { Pos : int Sprite : string Temperature : float UpdateBehaviour : 'a -> 'a }

我目前正在尝试使用F#进行试验,我正在努力解决如何最好地处理以下类型的场景:

[<Interface>]
type IStuff<'a> = 
    abstract member Update: 'a -> 'a

type Stuff1<'a> = {
    Pos : int 
    Sprite : string 
    Temperature : float 
    UpdateBehaviour  : 'a -> 'a 
} with 
    interface IStuff<'a> with
        member this.Update p = 
            this.UpdateBehaviour p
    static member New f = {
        Pos = 0
        Sprite = "Sprite"
        Temperature = 0.0
        UpdateBehaviour = f 
    }


type Stuff2<'a> = {
    Pos : int 
    UpdateBehaviour  : 'a -> 'a
} with 
    interface IStuff<'a> with
        member this.Update p = 
            this.UpdateBehaviour p
    static member New f = {
        Pos = 0
        UpdateBehaviour = f 
    }
这显然不起作用,因为编译器确定这两种类型明显不同,
Stuff1
为类型
'a
,而
Stuff2
为类型
'b

我也可以这样做

let stuffArr< 'T when 'T :> IStuff<'T>> = [|
    Stuff1.New<_> (fun p -> printfn "s1"; p)
    Stuff2.New<_> (fun p -> printfn "s2"; p)
|]
let stuffArr : obj list = [
    Stuff1.New<_> (fun p -> printfn "p1"; p)
    Stuff2.New<_> (fun p -> printfn "p2"; p)
]

let iterateThrough (l : obj list) = 
    l
    |> List.map (fun p -> 
        let s = p :?> IStuff<_> 
        s.Update p)
let stuffArr:obj list=[
Stuff1.新建(乐趣p->printfn“p1”;p)
Stuff2.新建(乐趣p->printfn“p2”;p)
]
让iterateThrough(l:obj列表)=
L
|>List.map(乐趣p->
设s=p:?>IStuff
s、 更新(p)
这很明显,但正如你们现在可能看到的,我基本上关闭了类型系统,我正在做一个动态的向下转换,坦率地说,这让我感到害怕


那么,有没有更好的方法来实现这一点?提前谢谢

有很多方法可以让你对现有的结构进行更多的检查,但这些方法都不是很好。然而,我认为最根本的问题是,您正试图将F#用作一种面向对象的语言。如果您使用更实用的设计,这将看起来更好

我将
东西
定义为与不同种类的东西有区别的结合:

type Stuff = 
  | Stuff1 of pos:int * sprite:string * temperature:float
  | Stuff2 of pos:int

let stuffArr = [
  Stuff1(0, "Sprite", 0.0)
  Stuff2(0)
]
更新操作将只是一个函数,它使用模式匹配来处理您拥有的两种不同类型的内容:

let update stuff = 
  match stuff with 
  | Stuff1 _ -> ...
  | Stuff2 _ -> ...
结果是,您只需使用
list.map
,即可更新所有内容并获得新列表:

List.map update stuffArr

我有种感觉,你上面展示的内容可能与你实际要做的事情不一样复杂。如果是这样,Tomas的解决方案可能太简单,您无法使用。如果您有某种原因喜欢使用上面描述的界面,您可以如下定义
stuffArr

let stuffArr : IStuff<_>[] = [|
    Stuff1.New<int> (fun p -> printfn "s1"; p)
    Stuff2.New<int> (fun p -> printfn "s2"; p)
|]
或者使用内置的
选项
类型

let stuffArr : IStuff<_>[] = [|
    Stuff1.New<Choice<string, int>> (fun p -> printfn "s1"; p)
    Stuff2.New<Choice<string, int>> (fun p -> printfn "s2"; p)
|]
let-stufgarr:IStuff[]=[|
Stuff1.新建(趣味p->printfn“s1”;p)
Stuff2.新建(乐趣p->printfn“s2”;p)
|]

Ok。如果我正在创建某种类型的库,并且我希望用户以某种组件式的方式创建自己的类型,那么就会出现问题。但这可能是这个特定问题的正确答案,谢谢!
let stuffArr : IStuff<_>[] = [|
    Stuff1.New<Choice<string, int>> (fun p -> printfn "s1"; p)
    Stuff2.New<Choice<string, int>> (fun p -> printfn "s2"; p)
|]