2012-04-23 15 views
8

Sto provando a leggere le righe di contenuto n in un elenco di stringhe. Ho provato diverse varianti del codice qui sotto, ma non ha funzionato.Leggi n righe in una [stringa]

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

Questo getta il seguente errore:

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 } 

E

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

tiri

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] 

Come posso fare questo?

+3

A proposito, 'input <- mapM (const getLine) [1 .. read input]' fa esattamente quello che ti serve. Il problema è che si tenta di mappare 'getLine' su numeri' [1 .. n] 'ma' getLine' non è una funzione. Usando 'const', lo trasformi in una funzione che ignora il suo primo argomento. – Vitus

+0

@Vitus che è degno come un'altra risposta, io lo faccio +1. – vikingsteve

risposta

42

Usa replicateM da Control.Monad:

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

Nello spirito di dare un uomo un pesce/insegnare ad un uomo a pescare: Si potrebbe avere trovato da soli cercando Hoogle.

Hai:

  • un'azione da eseguire di tipo IO String
  • un certo numero di volte per eseguire l'azione (tipo Int)

Volete:

  • un'azione di tipo IO [String]

Quindi potresti search Hoogle for (IO String) -> Int -> (IO [String]). replicateM è il primo hit.

0

Un altro modo in cui è possibile eseguire questa azione è utilizzando la replica pura e lo strumento sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) . Diciamo prima che chiederemo un conteggio e poi chiederemo che molti numeri interi stampino la loro somma sul terminale.

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