2013-10-28 60 views
3

我想要做以下的事情:一個方法getSessionToken這將:緩存一定時間的結果,並返回一個緩存值

  • 建立到服務器的請求,如果「cachedSessionToken」是過時的(由1個多小時前)

  • 一旦發出請求到服務器,這樣可以節省結果爲「variable」,然後返回它,每當getSessionToken被稱爲

所以這個想法是緩存一個結果,並在需要時返回,否則首先請求服務器getSessionTokenRemote,緩存它並且只有在返回結果後。我沒有興趣在具體實現的getSessionTokenRemote,但是,它可能是這樣的:

getSessionTokenRemote :: IO String 
-- or just 
getSessionTokenRemote :: String 

什麼是最合適的。

我想知道,我如何以純函數式語言如Haskell來做到這一點?

回答

5

如果你想getSessionTokenRemote寫入一個變量,你必須通過它,例如,給它一個這樣的類型:

type CacheInfo = {- you've got to fill this bit in -} 
getSessionTokenRemote :: IORef CacheInfo -> IO String 

一旦你採取這樣的類型,實現不是太難。

另一種方法是,如果執行隱藏,則寫入一個值,該值將產生getSessionTokenRemote值。假設內部實現上述類型和一些空緩存值emptyCacheInfo的,能夠這樣來完成:

getGetSessionTokenRemote :: IO (IO String) 
getGetSessionTokenRemote = getSessionTokenRemote <$> newIORef emptyCacheInfo 

這是一個IO動作被執行時,產生會話令牌獲取動作用新鮮緩存。

+0

請問您能解釋一下''CacheInfo','newIORef'和'emptyCacheInfo'是如何實現的嗎? –

+0

@Alex'newIORef'由['Data.IORef']提供(http://hackage.haskell.org/package/base-4.6.0.1/docs/Data-IORef.html#v:newIORef)。至於實現'CacheInfo'和朋友,那麼......你試過了什麼?什麼地方出了錯? –

+0

我只是不知道如何「寫入」CacheInfo,因爲Haskell沒有變量。我如何以及在哪裏存儲Haskell的值? –

3

Haskell確實有狀態變量,但它們是「管理」的。它們不可避免地會在一些monad中運行,並且您必須明確地讀取/寫入它們。 IORefMVar,TVar和朋友都是'管理參考'(我第一次聽到Clojure社區中使用的術語)。

這是一個令人毛骨悚然的簡化例子,說明如何使用ref類型來設置某些東西。

import Data.IORef 
import Network.HTTP 

data SessionToken = SessionToken { 
    _timeHours :: Int 
    , _token  :: String 
    } 

getSessionToken :: IORef SessionToken -> IO String 
getSessionToken cacheRef = do 
    cachedToken <- readIORef cacheRef 
    if _timeHours cachedToken > 1 
    then do 
    newToken <- getSessionTokenRemote 
    writeIORef cacheRef newToken 
    return $ _token newToken 
    else return $ _token cachedToken 

getSessionTokenRemote :: IO SessionToken 
getSessionTokenRemote = do 
    tokenRequest <- simpleHTTP $ getRequest "http://jtobin.ca/sample_token.txt" 
    token  <- getResponseBody tokenRequest 
    return $ SessionToken 0 token 

main :: IO() 
main = do 
    tokenRef <- newIORef $ SessionToken 0 "my token" 
    getSessionToken tokenRef >>= putStrLn 

    writeIORef tokenRef $ SessionToken 2 "my token" 
    getSessionToken tokenRef >>= putStrLn 
+0

我想這正是我正在尋找的! –

+0

tokenRef < - newIORef $ SessionToken 0「我的令牌」 - 這是否意味着我必須知道令牌?但起初我不知道。 –