簡體   English   中英

如何在 Haskell 中檢查兩個文件是否相等

[英]How to check that two files are equal in Haskell

我正在學習 Haskell,我需要比較兩個文件。 我沒有找到執行此操作的函數,因此我自己編寫了代碼。 下面是我想出的函數。

cmpFiles :: FilePath -> FilePath -> IO Bool
cmpFiles a b = withBinaryFile a ReadMode $ \ha ->
               withBinaryFile b ReadMode $ \hb ->
                 fix (\loop -> do
                   isEofA <- hIsEOF ha
                   isEofB <- hIsEOF hb

                   if | isEofA && isEofB -> return True             -- both files reached EOF
                      | isEofA || isEofB -> return False            -- only one reached EOF
                      | otherwise        -> do                      -- read content
                                              x <- hGet ha 4028     -- TODO: How to use a constant?
                                              y <- hGet hb 4028     -- TODO: How to use a constant?
                                              if x /= y
                                                then return False   -- different content
                                                else loop           -- same content, contunue...
                 )

我的問題是:

  1. 這段代碼是慣用的嗎? 它看起來非常必要,而不是功能性的。
  2. 這段代碼是否有效(Layz IO 問題與大文件、性能...)?
  3. 有沒有更緊湊的寫法?

怎么樣

cmpFiles a b = do
    aContents <- readFile a
    bContents <- readFile b
    return (aContents == bContents)

你甚至可以用它做一個單線:

cmpFiles a b = liftM2 (==) (readFile a) (readFile b)

這個其實相當於 Reid Barton 的解決方案。 如果您從hackageliftM2 liftM2的定義,則等效在這里不是一個狡猾的詞

liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }

並插入(==)readFile s,您立即在那里。

懶惰是你在 Haskell 中的朋友。 readFile 的文檔說明輸入是惰性讀取的,即僅按需讀取。 ==也很懶。 因此,整個liftM22 ...只讀取文件,直到找到差異為止。

cmpFiles a b = (==) <$> readFile a <*> readFile b

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM