传递函数作为参数

arp*_*pho 3 haskell

我是Haskell的新手,我应该编写一个函数,在其参数中使用一个函数,使用它并返回一个函数,其行为根据我传入的函数而变化,要清楚:在我的应用程序中:一个简单的缓存服务器,我读过一个上下文文件和所有参数之间的"LOG:活动"如果日志处于活动状态我必须在屏幕上给出日志以进行调试,否则我什么都不写,我不想使用if-then链,因此我想过写一个函数

setLogging a = do
   if a
   then let logging x = putStrLn x
    in  return logging
   else let logging x = putStrLn ""
        in return logging
Run Code Online (Sandbox Code Playgroud)

我以这种方式使用它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
Run Code Online (Sandbox Code Playgroud)

当我使用此功能时,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.
Run Code Online (Sandbox Code Playgroud)

我该如何修复这个程序?提前致谢

Tra*_*own 7

写出类型可能有助于开始reduceCache.您当前的版本具有以下类型:

reduceCache :: (Monad (M.Map k)) => Int -> ([Char] -> M.Map k a1) -> M.Map k a -> M.Map k a
Run Code Online (Sandbox Code Playgroud)

但我们知道第二个参数是类型的日志函数String -> IO (),所以有些不对劲.以下类型更有意义:

reduceCache :: Int -> (String -> IO ()) -> M.Map k v -> IO (M.Map k v)
Run Code Online (Sandbox Code Playgroud)

如果我们正在执行日志记录功能,我们知道我们需要最终进入IOmonad.我们只需要对您的实现进行一次更改以匹配新签名:

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

我们还可以简化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
Run Code Online (Sandbox Code Playgroud)

这应该做你想要的.请注意,setLogging并且setTrimming不再是monadic,所以你只需要写doLog = setLogging True(或let doLog = setLogging Truedo-expression中).