Ancora abbastanza nuovo per Haskell ..In Haskell, voglio leggere un file e poi scriverci sopra. Ho bisogno di annotazioni sulla severità?
Voglio leggere il contenuto di un file, fare qualcosa con esso possibilmente coinvolgendo IO (usando putStrLn per ora) e quindi scrivere nuovi contenuti nello stesso file.
mi si avvicinò con:
doit :: String -> IO()
doit file = do
contents <- withFile tagfile ReadMode $ \h -> hGetContents h
putStrLn contents
withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"
Tuttavia questo non funziona a causa di pigrizia. Il contenuto del file non viene stampato. Ho trovato this post che lo spiega bene.
la soluzione proposta non è quella di includere all'interno del putStrLn
withFile
:
doit :: String -> IO()
doit file = do
withFile tagfile ReadMode $ \h -> do
contents <- hGetContents h
putStrLn contents
withFile tagfile WriteMode $ \h -> hPutStrLn h "new content"
Questo funziona, ma non è quello che voglio fare. L'operazione in I sostituirà eventualmente putStrLn
potrebbe essere lunga, non voglio mantenere il file aperto tutto il tempo. In generale, voglio solo essere in grado di estrarre il contenuto del file e poi chiuderlo prima di lavorare con quel contenuto.
La soluzione mi è venuta è la seguente:
doit :: String -> IO()
doit file = do
c <- newIORef ""
withFile tagfile ReadMode $ \h -> do
a <- hGetContents h
writeIORef c $! a
d <- readIORef c
putStrLn d
withFile tagfile WriteMode $ \h -> hPutStrLn h "Test"
Tuttavia, ritengo che questo lungo e un po 'offuscato. Non penso che avrei bisogno di un IORef
solo per ottenere un valore, ma avevo bisogno di "posizionare" per mettere il contenuto del file. Inoltre, non funzionava ancora senza l'annotazione di rigore $!
per writeIORef
. Immagino che gli IORef
non siano rigorosi per natura?
Qualcuno può consigliare un modo migliore e più breve per farlo mantenendo la semantica desiderata?
Grazie!
Se pubblichi le dichiarazioni "import" necessarie per compilare il codice, altre persone potrebbero aiutarlo a eseguire il debug ... –
Ottimizzazione prematura, radici malvagie, ecc. Perché hai paura di mantenere il descrittore di file per tutto il tempo necessario vero? – jrockway
Lo IORef non ha l'effetto che percepisci. Un valore in uno IORef può essere altrettanto pigro di uno appena tornato da un blocco. Il tuo codice è equivalente a quello non funzionante: doit file = do { d <- conFile tagfile ReadMode $ \ h -> do { a <- hGetContents h; ritorno $! a }; ... Lo IORef è solo un cerchio senza senso da attraversare. Tuttavia, la battuta finale è che il seq regolare non è sufficiente per forzare un'intera stringa. Hai bisogno di un seq profondo. – luqui