2016-11-09 90 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