我當前正在學習Haskell,而且我很難看到在Haskell中保存中間結果的常用方法是什麼。Haskell - 將中間結果保存在內存中
例如,假設我有一個程序需要一個文件,產生一些中間結果,然後獲取一些參數並使用第一步的結果產生其他內容。另外,假設最終用戶可以改變參數以產生新的輸出,但是爲了減少計算時間,不應該重做第一步的處理。
基本上,我只需要暫時保存第一步的結果。對於我來說,這對於我來說相當簡單,但由於Haskell的純度,我沒有看到解決這個問題的方便方法。
我當前正在學習Haskell,而且我很難看到在Haskell中保存中間結果的常用方法是什麼。Haskell - 將中間結果保存在內存中
例如,假設我有一個程序需要一個文件,產生一些中間結果,然後獲取一些參數並使用第一步的結果產生其他內容。另外,假設最終用戶可以改變參數以產生新的輸出,但是爲了減少計算時間,不應該重做第一步的處理。
基本上,我只需要暫時保存第一步的結果。對於我來說,這對於我來說相當簡單,但由於Haskell的純度,我沒有看到解決這個問題的方便方法。
有很多方法可以處理Haskell中的中間結果。這聽起來像你希望你的main
函數看起來像這樣。我會假設你有一些函數產生的中間結果(runFirstStep
),對於設置(promptForSettings
)提示功能,而且採用了中間結果的功能和設置,以產生一個最終值(runSecondStep
)
main :: IO()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- processing
-- prompt for settings here
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- and done
print final
如果你想要一個更復雜的控制流,你可以定義一個單獨的函數,就像這樣:
main :: IO()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- run the second step computation
processLoop intermediate
print final
processLoop :: intermediate -> IO final
processLoop intermediate = do
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- check if user wants to run with different settings
rerun <- do
putStrLn "Run again? [Y/n]"
result <- getStrLn
return (result != "n")
if rerun
then process
else return final
如果你有興趣的是不純的,有許多方法來存儲中間計算更復雜的控制流在內存中使用各種技術。最低級別和最難得到的權利是使用IORef
。在此之上,您可以使用MVar
作爲基於某種共享狀態的信號和鎖定代碼部分的方式,但即使這樣做也很棘手,無法正確使用。在最高級別,ST
和STM
可讓您以更復雜的方式處理共享狀態,並且更容易推理。
一個例子:你想在一堆數字閱讀,然後計算這些數字(平方和,立方體的總和,等等)的權力不同數額
的第一步是「忽略IO「 - 暫時忘記你如何得到數字和功率參數 - 並專注於工作的肉的功能 - 計算一系列數字的n次冪的和。
powersum :: [Double] -> Int -> Double
powersum xs n = sum $ map (^n) xs
我們將要計算各種指數的功率和。同樣,我會忘了你要去以後與他們無關,無論是打印出來的東西,對它們進行排序等,並寫一個函數,它不計算:
powersums :: [Double] -> [Int] -> [Double]
powersums xs ns = map (powersum xs) ns
現在,讓我們把它掛到現實世界。讓我們首先考慮的情況下,當我們提前知道的指數,但是從標準輸入讀取的數字
main = do line <- getLine -- IO
let nums = map read (words line) \
let exponents = [1..10] | - pure code
let sums = powersums nums exponents /
print sums -- IO
注意如何我們的IO三明治我們的純代碼(在一行上所有) - 這是非常典型的功能性程序。
現在假設您還想從stdin中讀取指數,並打印出每個讀取指數的功率和。你可以寫一個命令式的程序是這樣的:
main = do line <- getLine
let nums = map read (words line)
forever $ do exp <- read `fmap` getLine
putStrLn $ show $ powersum nums exp
這說明了如何將數據(nums
在這種情況下)被儲存供程序的其他部分。