2012-04-23 14 views
8

Estoy tratando de leer n líneas de contenido en una lista de cadenas. Probé varias variaciones del código a continuación, pero nada funcionó.Lee n líneas en [String]

main = do 
    input <- getLine 
    inputs <- mapM getLine [1..read input] 
    print $ length input 

Esto arroja el siguiente error:

Couldn't match expected type `a0 -> IO b0' 
       with actual type `IO String' 
    In the first argument of `mapM', namely `getLine' 
    In a stmt of a 'do' block: inputs <- mapM getLine [1 .. read input] 
    In the expression: 
     do { input <- getLine; 
      inputs <- mapM getLine [1 .. read input]; 
      print $ length input } 

Y

main = do 
    input <- getLine 
    let inputs = map getLine [1..read input] 
    print $ length input 

tiros

Couldn't match expected type `a0 -> b0' 
       with actual type `IO String' 
    In the first argument of `map', namely `getLine' 
    In the expression: map getLine [1 .. read input] 
    In an equation for `inputs': inputs = map getLine [1 .. read input] 

¿Cómo puedo hacer esto?

+3

Por cierto, 'inputs <- mapM (const getLine) [1 .. read input]' hace exactamente lo que necesita. El problema es que tratas de mapear 'getLine' sobre números' [1 .. n] 'pero' getLine' no es una función. Al usar 'const', lo convierte en una función que simplemente ignora su primer argumento. – Vitus

+0

@Vitus que es digno de ser otra respuesta, la haré +1. – vikingsteve

Respuesta

42

Uso replicateM de Control.Monad:

main = do 
    input <- getLine 
    inputs <- replicateM (read input) getLine 
    print $ length inputs 

En el espíritu de dar a un hombre un pez/enseñar a un hombre a pescar: Usted podría haber encontrado esto por sí mismo mediante la búsqueda Hoogle.

Usted tiene:

  • una acción a realizar de tipo IO String
  • varias veces para llevar a cabo esa acción (tipo Int)

que desea buscar:

  • una acción de tipo IO [String]

Así que podría search Hoogle for (IO String) -> Int -> (IO [String]). replicateM es el primer golpe.

0

Otra forma en que puede hacer esta acción es utilizando la réplica pura y la herramienta sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) . Digamos que primero pediremos un recuento y luego pediremos muchos enteros para imprimir su suma en la terminal.

sumCountManyData :: IO() 
sumCountManyData = putStr "How many integers to sum..? " 
        >> getLine 
        >>= sequence . flip replicate getLine . read 
        >>= print . sum . map read 
Cuestiones relacionadas