haskell io ghc

Lea de stdin en Haskell usando IO.readLn



ghc (3)

Esto es a lo que le cambiaste el código, ¿verdad?

import System.IO main = do z <- readLn putStrLn z

putStrLn escribe una String en stdout, por lo que z es una String . Por readLn tanto, readLn leerá una String de stdin.

PERO ... readLn espera leer un valor con formato Haskell de stdin. es decir, en lugar de esperar que escriba algo como This is a string , lo anticipa entre comillas: "This is a string" .

Para solucionarlo, reemplace readLn con getLine , que se lee en texto literal, no en una cadena con formato Haskell.

import System.IO main = do z <- getLine putStrLn z

Este código no se compila en GHC 7.0.3:

import System.IO main = do z <- readLn print z

Mi intención es leer una línea de stdin y almacenarla en z, para hacer cosas más avanzadas con ella más adelante. El mensaje de error se ve así:

test.hs:5:9: Ambiguous type variable `a0'' in the constraints: (Show a0) arising from a use of `print'' at test.hs:5:9-13 (Read a0) arising from a use of `readLn'' at test.hs:4:14-19 Probable fix: add a type signature that fixes these type variable(s) In a stmt of a ''do'' expression: print z In the expression: do { z <- readLn; print z; return () } In an equation for `main'': main = do { z <- readLn; print z; return () }

Obviamente, hay algo fundamental que aún no entendí; por favor, explícame por qué no funciona y cómo solucionarlo.

EDIT1 : arreglé el error de compilación al cambiar print z por putStrLn z , por lo que GHC entiende que quiero leer una cadena. Pero cuando ejecuto el programa, obtengo un error de tiempo de ejecución que no puedo entender:

$ ./test hello! test: user error (Prelude.readIO: no parse) $

Acabo de escribir "hola!" y luego entrar Tenga en cuenta que estoy ejecutando x86_64 GHC en OS X, que se considera inestable.

EDIT2 : Cambié readLn a getLine y mágicamente funciona sin ninguna razón. Me gustaría saber por qué, pero estoy feliz de que funcione.

Código final:

import System.IO main = do z <- getLine print z


readLn como tipo: Read a => IO a . Lee una línea del usuario y luego analiza la cadena en el tipo a . ¿Qué es tipo a ? Es lo que quieras (siempre que sea una instancia de Read ). Por ejemplo:

readAInt :: IO Int readAInt = readLn readABool :: IO Bool readABool = readLn

print tiene el tipo Show a => a -> IO () . Toma un tipo que es una instancia de Show , y lo imprime. Por ejemplo, para imprimir True , puede usar print True . Para imprimir el Int 42, puede usar print 42 .

En su ejemplo, está usando print y readLn juntos. Esto no funciona, ya que haskell no puede descifrar qué tipo debe devolver readLn . print puede tomar cualquier tipo que se pueda mostrar, por lo que no se restringe a uno qué tipo se devolverá. Esto hace que el tipo de retorno de readLn ambiguo, ya que readLn no puede determinar el tipo. Esto es lo que está diciendo el mensaje de error.

Lo que probablemente es qué almacenar solo la cadena que ingresa el usuario, en lugar de leerla en su propio tipo. Puede hacerlo con getLine, que tiene el tipo getLine :: IO String . De manera similar, puede usar putStrLn lugar de print para simplemente imprimir una Cadena. putStrLn tiene el tipo String -> IO () .


readLn lee un tipo que especifique y, por lo tanto, no se puede usar de esta manera: debe usarse en una función que especifique su tipo. getLine, por otro lado, siempre devuelve un String, por lo que hace lo que quiere.

Vale la pena señalar que es posible que desee utilizar putStrLn en lugar de imprimir también; imprimir agregará comillas.

Por do { z <- getLine; putStrLn z; } tanto, do { z <- getLine; putStrLn z; } do { z <- getLine; putStrLn z; } do { z <- getLine; putStrLn z; } en GHCi debería hacer lo que quieras.