构造泛型函数

时间:2018-02-13 10:46:10

标签: f#

我有一个类型:

type DictionaryCache<'a, 'b when 'a :comparison>()

我还有另一种类型,其中包含一些DictionaryCache

type Cache() =

    let user = new DictionaryCache<int, User>()
    let userByLogin = new  DictionaryCache<string, User>()

    member this.User = user
    member this.UserByLogin = userByLogin

在最后一个类型中,我想创建一个泛型函数,它将根据输入参数返回一个成员:

member this.CacheNameToDictionary (cacheName: string) : DictionaryCache<'a, 'b> option = 
    match cacheName with
    | "userByAutoincrementedId" -> Some(this.User)
    | "userByLogin" -> Some(this.UserByLogin)
    | _ -> None

但由于type mismatch而无效。

有没有办法重写这个功能?

更新:这是我需要做的完整代码:

type Cache() =

    let user = new DictionaryCache<int, User>()
    let userByLogin = new  DictionaryCache<string, User>()

    static let mutable instance = lazy(new Cache())
    static member Instance with get() = instance.Value

    member this.User = user
    member this.UserByLogin = userByLogin

    member this.Get (useCache: string) (cacheName: string) (id: 'a) longFunction exceptionFunction : 'b option =  

        let nameToDictionary() : DictionaryCache<'a, 'b> option = 
            match cacheName with
            | "userByAutoincrementedId" -> Some(this.User)
            | "userByLogin" -> Some(this.UserByLogin)
            | _ -> None

        let foo() : 'b option = 
            try
                longFunction()   
            with 
            | exn -> exceptionFunction exn
                     None

        match (useCache, nameToDictionary()) with
        | "true", Some(dictionary) -> 
            match dictionary.Get id with 
            | Some(result) -> Some(result)
            | _ -> match foo() with 
                   | Some(result) -> dictionary.Put id result
                                     Some(result)
                   | _ -> None
        | _ -> foo()

1 个答案:

答案 0 :(得分:3)

这是不可能的 - 问题是方法的返回类型将取决于它作为输入参数获取的字符串。输入字符串仅在运行时已知,但类型需要在编译时知道。

您可以使用Choice类型,它可以让您返回多种不同类型之一:

member this.CacheNameToDictionary (cacheName: string) = 
    match cacheName with
    | "userByAutoincrementedId" -> Choice1Of3(this.User)
    | "userByLogin" -> Choice2Of3(this.UserByLogin)
    | _ -> Choice3Of3()

这样可行,但返回类型列出了所有三种选择并且非常难看:

Choice<DictionaryCache<int,User>, DictionaryCache<string,User>,unit>

此外,此方法的使用者必须对结果进行模式匹配,并以不同方式处理两个不同的词典,因此这可能不会使您的代码特别漂亮。

老实说,我认为您正在添加一个您不需要的抽象级别。如果有两个不同的密钥,那么您需要不同的代码来处理它,并且您不太可能编写可扩展的代码并添加第三种字典。