2010-08-22 151 views
2

我是新来的Haskell,我应该写一个函数,它的参数中的功能,使用它,并返回其行为变化取决于我传递的功能, 要明确一个功能:在我的应用程序:一个简单的缓存服务器,我读取一个上下文文件,并且在所有参数中,如果日志处于活动状态,则为“LOG:active”我必须在屏幕上给出日志以用于调试目的,否则我不写任何内容,我不想使用IF-THEN,因此,我认为写一个函数传递函数作为参数

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 

这应该做你想要什么。需要注意的是setLoggingsetTrimming不再单子,所以你只写doLog = setLogging True(或let doLog = setLogging Truedo -expression)。

+0

+1 Cool ...一切都涵盖 - 类型,语法,monads – Dario 2010-08-22 18:03:06