2016-11-09 78 views
1

我對Haskell是全新的,我找不到這個問題的答案。也許我在尋找錯誤的東西。Haskell比較IO UTCTime

我遇到了一個小應用程序需要兩個文件路徑和一個IO UTCTime時間戳的問題。這個想法是每5秒檢查目錄是否被修改。爲了簡單起見,我忽略了劇本的細節。它歸結爲:

import Data.List 
import Control.Monad 
import Control.Concurrent 
import System.Directory 
import Data.Time.Clock 

main = doLoop "FilePath" "FilePath" getCurrentTime 

doLoop lastPath currentPath lastModified = do 
    modified <- getModificationTime currentPath 
    if (lastModified /= modified) 
     then print "Success" 
     else do threadDelay 5000000 
       doLoop "FilePath" "FilePath" lastModified 

我得到的編譯錯誤:

Couldn't match expected type `UTCTime` 
with actual type `IO UTCTime` 
In the third argument of `doLoop`, namely `getCurrentTime` 

getCurrentTime應該產生一個IO UTCTime根據文檔,就像getCurrentTime。我在這裏錯過了什麼?

+0

如果您嘗試向'doLoop'添加類型簽名,您將會看到問題所在。一方面,你的'doLoop'期望它的第三個參數是'UTCTime',但是當你在'main'中調用它時,你給它一個'IO UTCTime'。嘗試將main更改爲:'main = do {currTime < - getCurrentTime; doLoop「FilePath」「FilePath」currTime}'(或者只是'main = doLoop「FilePath」「FilePath」=「currTime」)。 – Alec

+0

工作就像一個魅力。非常感謝你!是否因爲缺乏「do」調用,Haskell期望一個非單參數的參數而不是IO UTCTime,即使我使用的函數只能產生單子結果? – Ozan

+0

@Ozan不,它期望一個非'IO'的參數,因爲你把它傳遞給'(/ =)'以及另外一個非'IO'的東西。無論是使用'do'語法,還是最終產生'IO'都是相關的。 –

回答

3

IO UTCTime不是時間戳的類型。這是的一種動作,可以給你一個時間戳。這是一個巨大的差異。因此,它是沒有意義的doLoop接受一個IO UTCTime作爲其最後一個參數,可能是你想要的是

doLoop :: FilePath -> FilePath -> UTCTime -> IO() 

總是寫出類型簽名是這樣,找出錯誤真的發生並記錄你的意圖!

什麼不工作,那麼是doLoop "FilePath" "FilePath" getCurrentTime,因爲getCurrentTime動作獲得時間戳,而不是實際的時間戳。 (如果它只是一個時間戳,它幾乎是當前每當你怎麼稱呼它,可能嗎?)

因此,您需要評估這個動作得到一個實際的時間戳,然後可以傳遞給doLoop 。最簡單的方法是在do塊:

main = do 
    t <- getCurrentTime 
    doLoop "FilePath" "FilePath" t 

更簡潔,也可以Kleisli,構成這兩個IO操作:

main = doLoop "FilePath" "FilePath" =<< getCurrentTime 

...這實際上是什麼,do語法desugars來,無論如何。

+0

我明白了。當我調用這個函數時,我天真地期望Haskell插入當前時間戳作爲參數。感謝您指出我們的錯誤。 – Ozan