tags:

views:

129

answers:

1

Hi, I am new to Haskell,I should write a function that takes a function among its parameter, uses it and return a function whose behavior change depending the function I passed in, to be clear: in my application: a simple cache server, I read a context file and among all the parameter ther is "LOG: active"if log is active I have to give the log on the screen for debugfing purpose otherwise I write nothing, I do not want to use a chain of if-then, thus I thought of writing a function

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

I use it in this way doLog <- setLogging True and it works, I have problem with the function that should return the function for removing the old elements from my cache: how many element it must contain is determined by the context; this is my function

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

when I use this function with doTrimm <- setTrimming "active" I got this error

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.

how can I fix this program? thanks in advance

+6  A: 

It might help to start by writing out the type of reduceCache. Your current version has the following type:

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

But we know that the second argument is a logging function of type String -> IO (), so something's wrong. The following type makes more sense:

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

If we're executing the logging function, we know we need to end up in the IO monad. We only need to make one change to your implementation to match the new signature:

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

We can also simplify the set... functions:

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

This should do what you want. Note that setLogging and setTrimming are no longer monadic, so you'd just write doLog = setLogging True (or let doLog = setLogging True in a do-expression).

Travis Brown
+1 Cool ... everything covered - types, syntax, monads
Dario