Vor kurzem habe ich angefangen, Haskell zu lernen, weil ich mein Wissen über funktionale Programmierung erweitern wollte und ich muss sagen, dass ich es bis jetzt wirklich liebe. Die Ressource, die ich derzeit verwende, ist der Kurs 'Haskell Fundamentals Part 1' über Pluralsight. Leider habe ich einige Schwierigkeiten, ein bestimmtes Zitat des Dozenten über den folgenden Code zu verstehen, und ich hatte gehofft, dass Sie etwas Licht in das Thema bringen können.
Begleitcode
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
Das Zitat
Wenn Sie dieselbe E / A-Aktion mehrmals in einem Do-Block haben, wird sie mehrmals ausgeführt. Dieses Programm druckt also die Zeichenfolge 'Hello World' dreimal aus. Dieses Beispiel zeigt, dass putStrLnes sich nicht um eine Funktion mit Nebenwirkungen handelt. Wir rufen die putStrLnFunktion einmal auf, um die helloWorldVariable zu definieren . Wenn putStrLndas Drucken der Zeichenfolge einen Nebeneffekt hätte, würde sie nur einmal gedruckt, und die helloWorldim Haupt-Do-Block wiederholte Variable hätte keine Auswirkung.
In den meisten anderen Programmiersprachen würde ein Programm wie dieses 'Hello World' nur einmal drucken, da das Drucken beim Aufrufen der putStrLnFunktion erfolgen würde . Diese subtile Unterscheidung stolpert oft über Anfänger. Denken Sie also ein wenig darüber nach und stellen Sie sicher, dass Sie verstehen, warum dieses Programm 'Hello World' dreimal druckt und warum es nur einmal druckt, wenn die putStrLnFunktion den Druck als Nebeneffekt ausführt.
Was ich nicht verstehe
Für mich ist es fast selbstverständlich, dass die Zeichenfolge 'Hello World' dreimal gedruckt wird. Ich nehme die helloWorldVariable (oder Funktion?) Als eine Art Rückruf wahr, der später aufgerufen wird. Was ich nicht verstehe ist, wie wenn putStrLnein Nebeneffekt dazu führen würde, dass die Zeichenfolge nur einmal gedruckt wird. Oder warum es nur einmal in anderen Programmiersprachen gedruckt wird.
Nehmen wir im C # -Code an, ich würde annehmen, dass es so aussehen würde:
C # (Geige)
using System;
public class Program
{
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
public static void Main()
{
HelloWorld();
HelloWorld();
HelloWorld();
}
}
Ich bin sicher, ich übersehen etwas ganz Einfaches oder interpretiere seine Terminologie falsch. Jede Hilfe wäre sehr dankbar.
BEARBEITEN:
Vielen Dank für Ihre Antworten! Ihre Antworten haben mir geholfen, diese Konzepte besser zu verstehen. Ich denke, es hat noch nicht vollständig geklickt, aber ich werde das Thema in Zukunft noch einmal aufgreifen, danke!
putStrLn hat keine Nebenwirkung; Es wird einfach eine E / A-Aktion zurückgegeben, dieselbe E / A-Aktion für das Argument, "Hello World"unabhängig davon, wie oft Sie aufrufen putStrLn.
helloworldder Fall wäre , wäre dies keine Aktion, die gedruckt wird Hello world. es würde durch den Wert zurückgeführt werden , putStrLn nachdem es gedruckt Hello World(nämlich ()).
helloWorld = Console.WriteLine("Hello World");. Sie enthalten nur Console.WriteLine("Hello World");die HelloWorldFunktion, die bei jedem HelloWorldAufruf ausgeführt werden soll. Denken Sie jetzt darüber nach, was helloWorld = putStrLn "Hello World"macht helloWorld. Es wird einer E / A-Monade zugewiesen, die enthält (). Sobald Sie es daran gebunden haben, führt >>=es erst dann seine Aktivität aus (etwas drucken) und zeigt Sie ()auf der rechten Seite des Bindungsoperators an.
helloWorldeine Konstante wie ein Feld oder eine Variable in C # vor. Es gibt keinen Parameter, auf den angewendet wirdhelloWorld.