這個問題在這里已經有了答案: GHCi 和編譯后的代碼似乎表現不同 (1 個回答) 5 天前關閉。
今天我想讓 Haskell 表現得像任何命令式語言,看看這個:
import Data.HashMap.Strict as HashMap
import Data.Text.IO
import Data.Text
import Data.Functor ((<&>))
putStr "Reading data from file ..."
ls <- lines <$> readFile myFile
putStrLn " done."
putStr "Processing data ..."
let hmap = HashMap.fromList $ ls <&> \l -> case splitOn " " l of
[k, v] -> (k, v)
_ -> error "expecting \"key value\""
putStrLn " done."
基本上,用戶應該知道當前程式在做什么。這段代碼的結果是立即輸出
> Reading data from file ... done.
> Sorting data ... done.
...然后它開始做實際的作業,輸出違背了它的目的。
我很清楚這是一個功能。Haskell 是宣告性的,計算順序由實際依賴項決定,而不是由我的 .hs 檔案中的行號決定。因此,我嘗試以下方法:
putStr "Reading data from file ..."
lines <- lines <$> readFile myFile
putStrLn $ lines `seq` " done."
putStr "Processing data ..."
let hmap = HashMap.fromList $ ls <&> \l -> case splitOn " " l of
[k, v] -> (k, v)
_ -> error "expecting \"key value\""
putStrLn $ hmap `seq` " done."
這個想法:seq只有在它的第一個引數被評估為弱頭范式后才回傳。它有效,有點。我的程式的輸出現在暫時沒有任何內容,然后,一旦作業完成,所有 IO 就會發生。
有沒有辦法解決這個問題?
編輯:我改變了回答本的回答的問題。匯入現在應該更有意義并且程式真正運行。
DanielWagner 評論了這個相關問題:
GHCi 和編譯后的代碼似乎表現不同
這確實解決了我的問題。
putStrLn $ hmap `seq` " done."
做它應該做的。我只缺少重繪 標準輸出。所以這實際上做了我需要的:
putStr "Reading data from file ..."
hFlush stdout -- from System.IO
lines <- lines <$> readFile myFile
putStrLn $ lines `seq` " done."
putStr "Processing data ..."
hFlush stdout
let hmap = HashMap.fromList $ ls <&> \l -> case splitOn " " l of
[k, v] -> (k, v)
_ -> error "expecting \"key value\""
putStrLn $ hmap `seq` " done."
uj5u.com熱心網友回復:
您還沒有向我們提供您所說的具有這種行為的實際代碼:
我的程式的輸出現在暫時沒有任何內容,然后,一旦作業完成,所有 IO 就會發生。
我怎么知道這不是你正在運行的代碼?您的代碼根本無法編譯才能運行!幾個問題:
- 您收到來自 的型別錯誤
lines,因為它在標準中Prelude但該版本適用于String,并且您正在使用Text. - 你沒有
splitOn從任何地方進口 - 最明顯的
splitOn匯入是從Data.Text,但有一個型別Text -> Text -> [Text],即它回傳一個串列的Text在分離器的所有出現分裂。你顯然期待一對,只在第一個分隔符上分裂。
所以在非常最低,這是你正在運行的代碼ghci后,更多的進口/定義,你已經不是我們出。
盡可能少地改變它并讓它運行給了我這個:
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text.IO as StrictIO
import qualified Data.Text as Text
myFile = "data.txt"
main = do
putStr "Reading data from file ..."
lines <- Text.lines <$> StrictIO.readFile myFile
putStrLn $ lines `seq` " done."
putStr "Processing data ..."
let hmap = HashMap.fromList $ Text.breakOn " " <$> lines
putStrLn $ hmap `seq` " done."
我生成了一個包含 5,000,000 行的非常簡單的資料檔案并使用 運行程式runhaskell foo.hs,實際上在讀取/處理訊息的出現和每行出現的“完成”之間存在明顯的停頓。
我看不出為什么所有 IO 都會被延遲一次出現(包括第一個的結果putStrLn。您實際上如何運行此代碼(或者更確切地說,實際運行的完整和/或不同的代碼)?在帖子中,您已將其撰寫為 GHCi 的輸入而不是完整的程式(根據IO同一級別的匯入和陳述句判斷,沒有do任何頂級函式的塊或定義)。我唯一的想法是,也許您的資料檔案很多較小的,使得處理花費的時間幾乎沒有察覺量,Haskell代碼本身的初始啟動處理ghci或runhaskell是唯一顯著的延遲,然后我可以想象有被輕微的延遲,隨后所有的訊息的列印看似一次。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/387010.html
