2010-08-22 4 views
2

Я новичок в Haskell, я должен написать функцию, которая принимает функцию среди своего параметра, использует ее и возвращает функцию, поведение которой изменяется в зависимости от функции, в которой я прошел, , чтобы быть ясным: в моем приложении : простой сервер кеша, я читаю файл контекста, и среди всех параметров ther «LOG: active», если журнал активен, я должен предоставить журнал на экране для цели отладки, иначе я ничего не пишу, я не хочу использовать цепь если-то, таким образом, я думал о написании функцииПередача функций в качестве аргумента

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

Я использую его таким образом doLog <- setLogging True и это работает, у меня есть проблема с функцией, которая должна возвращать функцию для удаления старые элементы из моего кеша: сколько элементов он должен содержать, определяется контекстом; это моя функция

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

, когда я использую эту функцию с doTrimm <- setTrimming "active" я получил эту ошибку

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. 

как я могу исправить эту программу? Заранее благодарен

ответ

7

Это может помочь с помощью записи типа reduceCache. Ваша текущая версия имеет следующий вид:

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

Но мы знаем, что второй аргумент является протоколирование функция типа String -> IO(), так что-то не так. Следующий тип имеет смысл:

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

Если мы исполняем функцию регистрации, мы знаем, что мы должны в конечном итоге в IO монады. Нам нужно только сделать одно изменение в вашей реализации, чтобы соответствовать новой подписи:

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

Мы можем также упростить 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 

Это должно делать то, что вы хотите. Обратите внимание, что setLogging и setTrimming больше не являются монадическими, поэтому вы должны просто написать doLog = setLogging True (или let doLog = setLogging True в -выражение).

+0

+1 Прохладный ... все покрытое - типы, синтаксис, монады – Dario

Смежные вопросы