簡體   English   中英

hGetContents如何實現內存效率?

[英]How does hGetContents achieve memory efficiency?

我想將Haskell添加到我的工具箱中,所以我正在通過Real World Haskell工作

在輸入和輸出的章節中,在hGetContents的部分中 ,我遇到了這個例子:

import System.IO
import Data.Char(toUpper)

main :: IO ()
main = do 
    inh <- openFile "input.txt" ReadMode
    outh <- openFile "output.txt" WriteMode
    inpStr <- hGetContents inh
    let result = processData inpStr
    hPutStr outh result
    hClose inh
    hClose outh

processData :: String -> String
processData = map toUpper

根據此代碼示例,作者繼續說:

請注意, hGetContents為我們處理了所有的閱讀。 另外,看一下processData 它是一個純函數,因為它沒有副作用,並且每次調用時總是返回相同的結果。 在這種情況下,它沒有必要知道 - 也沒有辦法告訴它在文件中懶惰地讀取它的輸入。 它可以與磁盤上的20個字符的文字或500GB數據轉儲完美配合。 (NB重點是我的)

我的問題是: hGetContents或其結果值如何在沒有 - 在這個例子中 - processData “能夠告訴”,並且仍然保持純代碼(即processData ),特別是memoization的所有好處的情況下實現這種內存效率?

<- hGetContents inh返回一個字符串,因此inpStr綁定到String類型的值,這正是processData接受的類型。 但是,如果我正確理解了真實世界Haskell的作者,那么這個字符串就不像其他字符串那樣,因為它沒有完全加載到內存中(或者如果存在未完全評估的字符串這樣的東西,則完全評估它。 。)在調用processData

因此,問我的問題的另一種方法是:如果在調用processData時沒有對inpStr進行全面評估或加載到內存中,那么如何在沒有首先完全評估inpStr情況下查找是否存在對processData的memoized調用inpStr

是否存在類型為String實例,每個實例的行為都不同但在此抽象級別上無法分開?

hGetContents返回的String與任何其他Haskell字符串沒有區別。 通常,除非程序員采取額外步驟來確保它(例如seqdeepseq ,bang模式),否則不會對Haskell數據進行全面評估。

字符串定義為(基本上)

data List a = Nil | Cons a (List a) -- Nil === [], Cons === :
type String = List Char

這意味着字符串是空的,或者是單個字符(頭部)和另一個字符串(尾部)。 由於懶惰 ,尾巴可能不存在於記憶中,甚至可能是無限的。 在處理String ,Haskell程序通常會檢查它是否為NilCons ,然后根據需要進行分支和繼續。 如果函數不需要評估尾部,則不會。 例如,此函數只需要檢查初始構造函數:

safeHead :: String -> Maybe Char
safeHead [] = Nothing
safeHead (x:_) = Just x

這是一個完全合法的字符串

allA's = repeat 'a' :: String

這是無限的。 您可以合理地操作此字符串,但是如果您嘗試打印所有字符串,或計算長度,或任何類型的無界遍歷,您的程序將不會終止。 但是你可以safeHead使用safeHead函數,甚至可以使用一些有限的初始子字符串。

然而,你發現某些奇怪事情的直覺是正確的。 hGetContents是使用特殊函數unsafeInterleaveIO實現的 ,它本質上是IO行為的編譯器鈎子。 對此越少說越好。

你是正確的,如果沒有完全評估參數,就很難檢查是否存在對函數的memoized調用。 但是,大多數編譯器不執行此優化。 問題是編譯器很難確定何時值得記住調用,並且很容易通過這樣做來消耗所有內存。 幸運的是,有幾個memoizing庫可以用來在適當的時候添加memoization。

暫無
暫無

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

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