file - print - Lectura de archivos haskell
print haskell (3)
¡No es un mal comienzo! Lo único que hay que recordar es que la aplicación de función pura debe usar let
lugar del enlace <-
.
import System.IO
import Control.Monad
main = do
let list = []
handle <- openFile "test.txt" ReadMode
contents <- hGetContents handle
let singlewords = words contents
list = f singlewords
print list
hClose handle
f :: [String] -> [Int]
f = map read
Este es el cambio mínimo necesario para que la cosa se compile y ejecute. Estilísticamente, tengo algunos comentarios:
- La
list
enlaces dos veces se ve un poco sombría. Tenga en cuenta que esto no está mutando lalist
valores, sino que está siguiendo la definición anterior. - Funciones puras en línea mucho más!
- Cuando sea posible, es preferible usar
readFile
a abrir, leer y cerrar un archivo manualmente.
Implementar estos cambios da algo como esto:
main = do
contents <- readFile "test.txt"
print . map readInt . words $ contents
-- alternately, main = print . map readInt . words =<< readFile "test.txt"
readInt :: String -> Int
readInt = read
Hace poco empecé a aprender Haskell y tengo muchos problemas para entender cómo funciona la lectura del archivo.
Por ejemplo, tengo un archivo de texto "test.txt" Y contiene líneas de números, por ejemplo:
32 4
2 30
300 5
Quiero leer cada línea y luego evaluar cada palabra y agregarlas. Así que estoy tratando de hacer algo como esto hasta ahora:
import System.IO
import Control.Monad
main = do
let list = []
handle <- openFile "test.txt" ReadMode
contents <- hGetContents handle
singlewords <- (words contents)
list <- f singlewords
print list
hClose handle
f :: [String] -> [Int]
f = map read
Sé que esto es completamente incorrecto, pero no sé cómo usar la sintaxis correctamente. Cualquier ayuda será apreciada. Además de los enlaces a buenos tutoriales que tienen ejemplos y explicaciones de código, excepto este: http://learnyouahaskell.com/input-and-output Lo he leído completamente
La solución de Daniel Wagner es excelente. Aquí hay otro giro para que pueda obtener más ideas sobre el manejo eficiente de archivos.
{-# LANGUAGE OverloadedStrings #-}
import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List
sumNums :: B.ByteString -> Int
sumNums s = foldl'' sumStrs 0 $ B.split '' '' s
sumStrs :: Int -> B.ByteString -> Int
sumStrs m i = m+int
where Just(int,_) = B.readInt i
main = do
sums <- map sumNums <$> B.lines <$> B.readFile "testy"
print sums
Primero, verás el pragma OverloadedStrings. Esto permite usar solo comillas normales para literales de cadena que en realidad son octetos. Usaremos Lazy ByteStrings para procesar el archivo por varias razones. Primero, nos permite transmitir el archivo a través del programa en lugar de forzarlo a la memoria a la vez. Además, los desvíos son más rápidos y más eficientes que las cadenas en general.
Todo lo demás es bastante sencillo. Leemos el archivo en una lista de líneas perezosa y luego asignamos una función de suma a cada una de las líneas. Los <$>
son solo accesos directos que nos permiten operar con el valor dentro del functor IO () - si esto es demasiado, me disculpo. Solo quiero decir que cuando lee Archivo no recupera un ByteString, recibe un ByteString envuelto en IO y IO (ByteString). El <$>
dice "Oye ''Quiero operar la cosa dentro de la IO y luego envolverla de nuevo.
B.split separa cada línea en números basados en espacios en blanco. (También podríamos usar B.words para esto) La única otra parte interesante es que en sumStrs
usamos la deconstrucción / el patrón de comparación para extraer el primer valor del Just que devuelve la función readInt.
Espero que esto haya sido útil. Pregunta si tienes alguna duda.
Para todos los programadores no funcionales que hay por aquí, es un regalo.
unsafePerformIO . readFile $ "file.txt"
Lee un archivo en una cadena
Sin cadena de E / S, solo una cadena normal completamente cargada y lista para usar. Puede que esta no sea la forma correcta, pero funciona y no es necesario cambiar las funciones existentes para que se adapten a la cadena IO
ps no te olvides de importar
import System.IO.Unsafe