2015-04-07 15 views
9

Ich habe eine Funktion blabla in Haskell, die ein Int nimmt und gibt einen String zurück:Wie kann ich IO-Befehle wiederholt in Haskell ausführen?

blabla :: Int -> [Char] 

Ich möchte ein, dass die Methode wiederholt laufen for-Schleife, so etwas wie dieses:

for i := 1 to 25 do begin 
    write(i); 
    write(": "); 
    writeln(blabla(i)); 
end; 

Does Haskell haben eine For-Loop-Funktion?

+4

So können Sie eine Funktion vom Typ wollen '[etwas] -> IO()', im Wesentlichen? Das wäre 'mapM_ print' nach' import Control.Monad'. – AJFarmar

Antwort

13

Es gibt eine forM_ Funktion im Control.Monad-Modul, das für die Schleife in imperativen Programmiersprachen auf ein ähnlich ist:

import Control.Monad (forM_) 

blabla :: Int -> String 
blabla = show 

main = forM_ [1..25] $ \i -> do 
    putStr (show i) 
    putStr ": " 
    putStrLn (blabla i) 

Allerdings würde ich Sie raten, aus solchen Imperativ Artcode zu. Zum Beispiel kann der gleiche Code prägnanter geschrieben werden als:

import Control.Monad (mapM_) 

blabla :: Int -> String 
blabla = show 

main = mapM_ (\i -> putStrLn $ show i ++ ": " ++ blabla i) [1..25] 

Hoffnung, die hilft.

+1

'blabla = (: []). ("blabla" !!) '? – Mokosha

+1

@Mokosha 'blabla x = Blabla x'. –

+0

"Ich würde dir empfehlen, dich von einem solchen imperativen Stilcode fernzuhalten" - Füge eine Alternative hinzu, die du für besser hältst, und du wirst meine Stimme für diese Antwort haben. – bheklilr

2

Sie denken immer noch prozesstechnisch. Versuchen Sie, eher in Listen als in Schleifen zu denken.

Dann, was Sie wollen, ist eine Liste wie folgt aus: [1,f(1),2,f(2),3,f(3)...,n,f(n)]

Hier map das Bild eintritt. Wenn Sie eine Funktion f hatten und diese auf eine Liste [1,2,3...,n] anwenden wollten, verwenden Sie map f [1..n].

Was Sie wollen, ist eine Funktion, die eine Zahl nimmt i und wendet eine Funktion f darauf, antwortet dann mit [i,f(i)] oder vielleicht ein Tupel (i,f(i)). Sie erstellen diese Funktion und ordnen sie Ihrer Liste zu.

Und natürlich müssen Sie diese erste Liste erstellen, um auf - diese Liste von [1..n] zu arbeiten.

Ein weiterer Ansatz ist es, eine Liste Verständnis zu verwenden:

forloop n = [(x,f x)|x <- [1..n] ] 

(Anmerkung: Ich habe keinen Haskell Compiler mit mir jetzt, also muss ich später den letzten Teil überprüfen ich glaube, es sollte wie vorgestellt arbeiten.).

+0

Nun, mein Problem ist, wie man PutStrLn in solch einer Karte bekommt ... Hast du ein Beispiel? – Hennes

+0

Sehen Sie sich den Typ von putStrLn und die Art von Elementen in Ihrer Liste an (die 25 Elemente enthalten sollten). – zcleghern

+0

'putStrLn' verwendet IO, was es komplizierter macht. Aber Sie müssen das nicht in die Karte bringen - Sie können einen vollständigen String erstellen und ihn später mit putStrLn ausgeben. –

0

Ich glaube, ich habe es selbst:

blablaOutput :: [Int] -> IO() 
blablaOutput (x:xs) = do 
    putStrLn (blabla x) 
    blablaOutput xs 
blablaOutput _ = putStrLn "That's all, folks!" 

main = blablaOutput [0..25] 

Sicher nicht sehr funktional in den Mitteln der funktionalen Programmierung, aber es funktioniert.

+4

Das funktioniert sicherlich, und es ist nichts falsch mit der expliziten Rekursion, wie Sie es gerade getan haben. Sie werden feststellen, dass gängige Muster wie das obige in der Standardbibliothek ihren Platz haben. Zum Beispiel 'main = do mapM_ (putStrLn. Blabla) [0..25]; putStrLn "Das ist alles, Leute!" ist gleichbedeutend mit dem oben genannten. – chi

7

Auf eine Tasse Tee zu trinken, ich das beste Ergebnis bekam, denke ich:

blablaResults = map (\x -> show x ++ ":" ++ blabla x) [0..25] 

main = putStrLn $ unlines blablaResults 
+4

Für diesen speziellen Fall halte ich dies für den besten Ansatz, da er Rechenleistung und E/A klar voneinander trennt. – chi

+0

Ja, jetzt denkst du in einem funktionalen Stil. BTW, Sie könnten dies in eine Zeile schneiden "main = mapM_ (\ x -> putStrLn $ anzeigen x ++": "++ blabla x) [0.25]". –

+0

Wie ich bereits bei @ user2407038 erwähnt habe, fügen sowohl 'putStrLn' als auch' unlines' einen letzten Zeilenumbruch hinzu. –

Verwandte Themen