F # Общая проблема: не может быть обобщена, потому что она выходит за рамки - PullRequest
2 голосов
/ 10 декабря 2010

Я определил это в общем месте:

[<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. Есть ли способ преодолеть эту ошибку

Everythign компилируется путем удаления путем ввода параметра в строку:

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

ОДНАКО Я хочу иметь возможность запомнить, больше, чем функции с подписью: String Action <_>, в идеале строка может быть int, float, object - что угодно ...

1 Ответ

4 голосов
/ 10 декабря 2010

Проблема в том, что вы указали параметр единственного типа 'T в своем определении createCache, но когда вы создаете его в memoizeSingleParamWithCallback, вы хотите получить обратно Dictionary<'P, 'R option>. На самом деле вы можете просто удалить некоторые параметры типа и аннотации, чтобы ваш код работал:

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)

Теперь F # выводит наиболее общие применимые типы, в результате чего createCache корректно зависит от двух неявных параметров типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...