ツールボックスに 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 文字のリテラルまたはディスク上の 500 GB のデータ ダンプで完全に機能します。 (注:強調は私のものです)
私の質問はhGetContents
、この例では「伝えることができない」ことなく、またはその結果の値がこのメモリ効率をどのように達成し、純粋なコード (つまり、メモ化) に生じるprocessData
すべての利点を維持するのですか?processData
<- hGetContents inh
は文字列を返すためinpStr
、 type の値にバインドされます。これは、受け入れるString
型とまったく同じです。processData
しかし、Real World Haskell の作成者を正しく理解していれば、この文字列はメモリに完全にロードされていない (または完全に評価されていない文字列が存在する場合は完全に評価されていない) という点で、他の文字列とはまったく異なります。 .) への呼び出し時までにprocessData
。
したがって、私の質問をする別の方法は次のとおりです。inpStr
への呼び出し時に が完全に評価されていないか、メモリにロードされていない場合、最初に を完全に評価せずに、processData
へのメモ化された呼び出しが存在するかどうかを調べるためにどのように使用できますか?processData
inpStr
String
それぞれが異なる動作をするが、このレベルの抽象化では区別できないタイプのインスタンスはありますか?