如何在不丢失原始类型的情况下接收扩展接口的类型

Des*_*ino 3 f#

我刚刚开始使用F#,我的大脑已经破碎,试图弄清楚如何使用它的类型,而不必采用OO类型的编程.

这是我的情况我基本上想要创建一个方法,我提供类型和Id,它返回给我数据库中的对象.

所以基本上这就是我到目前为止所得到的.

let client = MongoClient()
let database = client.GetDatabase("testdb")

let lowerCase (str : string) = 
    str.ToLower()

let nameOf (classType: Type) = 
    classType.Name

let nameTypeOf<'a> = 
    nameOf typeof<'a>   

let getCollection<'a> =
    let collectionName = nameTypeOf<'a> |> lowerCase
    database.GetCollection<'a> collectionName

let dbSelect<'a> id = 
    let collection = getCollection<'a>
    collection.Find(fun(x) -> x.Id = id).First()
Run Code Online (Sandbox Code Playgroud)

所以我的问题是使用dbSelect,显然它不编译,因为x是通用的,基本上我想创建一个带有Id的接口,所有我的对象都与它接口.我知道如何使用类和继承来实现它,但我避免在cop库之外使用实例化的类.如果有的话,最好的功能方法是什么.

这就是我所期待的

type IDbObject = 
    abstract Id: string

type Item = 
    {
        Id: string
        Name: string
    }
    interface IDbObject with
        member x.Id = x.Id

let item = 
    selectDb<Item> "5993592a35ce962b80da1e22"
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.如果有人想指出我的代码是多么糟糕,任何反馈都非常感谢

scr*_*wtp 5

我不认为这里的解决方案与您在C#中的解决方案有很大不同.您可以约束泛型类型以使用接口成员,获得大致如下所示的内容:

let getCollection<'a when 'a :> IDbObject> () =
   let collectionName = nameTypeOf<'a> |> lowerCase
   database.GetCollection<'a> collectionName

let dbSelect<'a when 'a :> IDbObject> id =
   let collection = getCollection<'a>()
   collection.Find(fun (x : 'a) -> x.Id = id).First()
Run Code Online (Sandbox Code Playgroud)

dbSelect应该推断出类型string -> #IDbObject,并string -> 'a在呼叫站点被强制执行.