2010-08-22 7 views
2

Je suis nouveau à Haskell, je devrais écrire une fonction qui prend une fonction parmi ses paramètres, l'utilise et retourne une fonction dont le comportement change selon la fonction que j'ai passée, pour être clair: dans mon application : un simple serveur de cache, je lis un fichier de contexte et parmi tous les paramètres ther est "LOG: active" si log est actif je dois donner le log sur l'écran à des fins de débogage sinon je n'écris rien, je ne veux pas utiliser une chaîne de if-then, donc je pensais écrire une fonctionpasser des fonctions comme argument

setLogging a = do 
    if a 
    then let logging x = putStrLn x 
    in return logging 
    else let logging x = putStrLn "" 
     in return logging 

Je l'utilise de cette façon doLog <- setLogging True et il fonctionne, j'ai problème avec la fonction qui doit retourner la fonction pour enlever les anciens éléments de mon cache: le nombre d'éléments qu'il doit contenir est déterminé par le contexte; c'est ma fonction

--ritorna la funzione che riduce la cache in funzione dell environment 
setTrimming a = do 
    if a=="active" 
      then let trimming c logging = reduceCache 9 logging c --è attivo lowbandwidth 
       in return trimming 
      else let trimming c logging = reduceCache 5 logging c --non è attivo lowbandwidth 
       in return trimming 

reduceCache s log cache 
    | (M.size cache) >= s = do 
     log "LOG: ciao" 
     reduceCache s log (snd (M.deleteFindMin cache)) 
    | otherwise = cache 

lorsque j'utilise cette fonction avec doTrimm <- setTrimming "active" j'eu cette erreur

ghc --make "trimmer.hs" (in directory: /media/Volume/doc/progetti/haskell) 
[1 of 1] Compiling Main    (trimmer.hs, trimmer.o) 
trimmer.hs:33:31: 
Couldn't match expected type `t1 -> t' 
     against inferred type `M.Map k a' 
In the expression: reduceCacheLow 9 logging c 
In the definition of `trimming': 
    trimming c logging = reduceCacheLow 9 logging c 
In the expression: 
    let trimming c logging = reduceCacheLow 9 logging c 
    in return trimming 
trimmer.hs:35:30: 
Couldn't match expected type `t1 -> t' 
     against inferred type `M.Map k a' 
In the expression: reduceCacheHigh 4 logging c 
In the definition of `trimming': 
    trimming c logging = reduceCacheHigh 4 logging c 
In the expression: 
    let trimming c logging = reduceCacheHigh 4 logging c 
    in return trimming 
Compilation failed. 

comment puis-je résoudre ce programme? merci d'avance

Répondre

7

Il peut être utile de commencer par écrire le type reduceCache. Votre version actuelle a le type suivant:

reduceCache :: (Monad (M.Map k)) => Int -> ([Char] -> M.Map k a1) -> M.Map k a -> M.Map k a 

Mais nous savons que le second argument est une fonction d'enregistrement de type String -> IO(), donc quelque chose qui ne va pas. Le type suivant est plus logique:

reduceCache :: Int -> (String -> IO()) -> M.Map k v -> IO (M.Map k v) 

Si nous nous exécutons la fonction de journalisation, nous savons que nous devons finir dans le IO monade. Nous avons seulement besoin de faire un changement à votre mise en œuvre pour correspondre à la nouvelle signature:

reduceCache s log' cache 
    | M.size cache >= s = do 
    log' "LOG: ciao" 
    reduceCache s log' (snd $ M.deleteFindMin cache) 
    | otherwise = return cache 

On peut aussi simplifier les fonctions set...:

setLogging :: Bool -> String -> IO() 
setLogging True = putStrLn 
setLogging False = const $ return() 

setTrimming :: String -> M.Map k v -> (String -> IO()) -> IO (M.Map k v) 
setTrimming "active" = \c logging -> reduceCache 9 logging c 
setTrimming _  = \c logging -> reduceCache 5 logging c 

Cela devrait faire ce que vous voulez. Notez que setLogging et setTrimming ne sont plus monadiques, donc vous devez simplement écrire doLog = setLogging True (ou let doLog = setLogging True dans une expression do).

+0

+1 Cool ... tout couvert - types, syntaxe, monades – Dario

Questions connexes