2010-12-10 3 views
2

Je possède ce sens dans un lieu commun:F # Problème générique: ne peut pas être généralisée car elle échapper à son champ d'application

[<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) 

Et je tente de l'utiliser comme ceci:

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


let findTickersMemoize = memoizeSingleParamWithCallback<ResultObject array, string> findTickers 

et recevoir cette erreur sur la définition de la fonction memoize:

Ce code n'est pas suffisamment générique. La variable de type 'P when' P: l'égalité n'a pas pu être généralisée car elle échapperait à son étendue.

Mes deux questions sont:

  1. Qu'est-ce que cette erreur me disant
  2. Y at-il un moyen de surmonter cette erreur

everythign compile en supprimant par le paramètre en tapant à la chaîne:

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

CEPENDANT vouloir être en mesure de mémoize, plus de fonctions avec une chaîne: Action < _> signature, idéalement la chaîne pourrait être un int, float, objet - peu importe ...

+0

Veuillez fournir un exemple complet - sans les définitions de 'createCache',' ResultObject', et 'commonProxyRpc', il est difficile de dire ce qui ne va pas. – kvb

+0

Thks - Je pense que j'ai ajouté assez d'étudiante pour faire un échantillon plus complet. Tout fonctionne si je suppose une chaîne par opposition à P pour le type de la variable param4eter, mais la fonction devrait être en mesure d'être un peu plus générique – akaphenom

Répondre

3

Le problème est que vous avez fourni un seul type le paramètre 'T sur votre définition de createCache, mais lorsque vous l'instanciez dans memoizeSingleParamWithCallback, vous souhaitez obtenir un Dictionary<'P, 'R option>. Vous pouvez en fait juste supprimer certains des paramètres de type et des annotations pour obtenir votre code fonctionne:

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) 

maintenant F # infère les types les plus généraux qui sont applicables, ce qui entraîne createCache correctement selon deux paramètres de type implicite.

Questions connexes