F#一般问题:无法推广,因为它会逃避其范围

时间:2010-12-10 15:51:22

标签: generics f#

我在一个共同的地方定义了这个:

[<DataContract>]
type ResultObject = {
    [<DataMember>]
    mutable field1: string
    [<DataMember>]
    mutable field2: string
    [<DataMember>]
    mutable field3: int 
}

let createCache<'T> () =
    Dictionary<_, 'T option>(HashIdentity.Structural)  


let memoizeSingleParamWithCallback<'R, 'P when 'P : equality>  functionToMemoize =    

    let cache = createCache<'R>() 

    // return a function that takes two parameters a parameter to the functionToMemoize  and a callback 
    fun (parameter: 'P) (callback: Action<_>) ->
        // form a unique cache key the parameterValue
        let key = parameter

        // check to see if the cache contains they key
        match cache.ContainsKey(key) with
        // if so invoke the callback with the cache value (need to conver to Some)
        | true -> callback.Invoke(cache.[key])
        // if not, invoke the RPC function, store the value, and perform the callback
        | false ->
            // create an internim callback to intercept the RPC function results, 
            //     store the value, and perform the final callback
            let updateCache (results: 'R option) = 
                match results with
                // no results returned - invoke call back with None none
                | None -> 
                    cache.[key] <- None
                    callback.Invoke(None)
                // results returned - store them and invoke the call back 
                | Some result -> 
                    cache.[key] <- Some(result)
                    callback.Invoke(Some(result))
            functionToMemoize parameter  <| new Action<_>(updateCache)

我试图这样使用它:

let findTickers (partialTicker : String) (callbackUI : Action<_>) =
    let lstOfResultObjects = [{field1=""; field2=""; field3=3}]
    callbackUI.Invoke(Some(lstOfResultObjects))


let findTickersMemoize = memoizeSingleParamWithCallback<ResultObject array, string>  findTickers 

并在memoize函数定义中收到此错误:

  

此代码不够通用。   P时的类型变量'P:   平等不能一概而论   因为它会逃避它的范围。

我的两个问题是:

  1. 告诉我的错误是什么
  2. 有没有办法克服这个错误
  3. Everythign通过键入参数删除来编译:

     fun (parameter: 'P) (callback: Action<_>) ->
         ()
    

    然而,我希望能够记忆,而不是使用以下函数:String Action&lt; _&gt;签名,理想情况下,字符串可以是int,float,object - 无论如何......

1 个答案:

答案 0 :(得分:4)

问题是您在'T的定义上提供了单个类型参数createCache,但是当您在memoizeSingleParamWithCallback中实例化它时,您想要获得{{1} }}。实际上,您只需删除一些类型参数和注释即可使代码正常工作:

Dictionary<'P, 'R option>

现在F#推断出最适用的一般类型,这会导致let createCache() = Dictionary<_, _>(HashIdentity.Structural) let memoizeSingleParamWithCallback functionToMemoize = let cache = createCache() // return a function that takes two parameters a parameter to the functionToMemoize and a callback fun (parameter: 'P) (callback: Action<_>) -> // form a unique cache key the parameterValue let key = parameter // check to see if the cache contains they key match cache.ContainsKey(key) with // if so invoke the callback with the cache value (need to conver to Some) | true -> callback.Invoke(cache.[key]) // if not, invoke the RPC function, store the value, and perform the callback | false -> // create an internim callback to intercept the RPC function results, // store the value, and perform the final callback let updateCache (results: 'R option) = match results with // no results returned - invoke call back with None none | None -> cache.[key] <- None callback.Invoke(None) // results returned - store them and invoke the call back | Some result -> cache.[key] <- Some(result) callback.Invoke(Some(result)) functionToMemoize parameter <| new Action<_>(updateCache) 正确,具体取决于两个隐式类型参数。