Я понимаю, что я не должен пытаться перечитываю из stdin
из-за ошибок о Haskell IO - handle closed Например, в поле ниже:Как эффективно повторно использовать входные данные из стандартного ввода в Haskell
main = do
x <- getContents
putStrLn $ map id x
x <- getContents --problem line
putStrLn x
второй вызов x <- getContents
вызовет ошибка:
test: <stdin>: hGetContents: illegal operation (handle is closed)
конечно, я могу опустить вторую линию для чтения из getContents
.
main = do
x <- getContents
putStrLn $ map id x
putStrLn x
Но будет ли это проблемой производительности/памяти? Будет ли GHC хранить все содержимое с stdin
в основной памяти?
Я предполагаю, что в первый раз, когда потребляется x
, GHC может выбросить порты x
, которые уже обработаны. Поэтому теоретически GHC может использовать только небольшую часть постоянной памяти для обработки. Но так как мы снова будем использовать x
(и снова), похоже, что GHC ничего не может выбросить. (И он не может читать снова с stdin
).
Мое понимание влияния памяти здесь правильно? И если да, есть ли исправление?
Да, он должен хранить все stdin в памяти. Я не вижу, как будет возможно исправление: хотите ли вы, чтобы ваша программа удаляла данные и все еще имела ее позже? Возможно, вы ищете что-то вроде 'do x <- getContents; y <- useMyDataSomehow x; useMoreData y'? В любом случае ваша проблема может быть решена библиотеками каналов/каналов (за счет написания вашей программы в стиле, требуемом этими библиотеками) – chi
У вас это точно верно 'do {cs <- getContents; putStrLn cs} 'использует в основном память,' do {cs <- getContents; putStrLn cs; putStrLn cs} 'накапливает все' cs' в первый раз. Как вы обойдетесь, это будет зависеть от того, что вы делаете.Вы буквально хотите «putStrLn» дважды? Или, например, длину записи и печать, или что? – Michael
Грубо говоря, я хочу использовать Haskell для реализации UNIX 'tee' или его варианта. – tinlyx