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 putStrLn
es sich nicht um eine Funktion mit Nebenwirkungen handelt. Wir rufen die putStrLn
Funktion einmal auf, um die helloWorld
Variable zu definieren . Wenn putStrLn
das Drucken der Zeichenfolge einen Nebeneffekt hätte, würde sie nur einmal gedruckt, und die helloWorld
im 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 putStrLn
Funktion 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 putStrLn
Funktion 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 helloWorld
Variable (oder Funktion?) Als eine Art Rückruf wahr, der später aufgerufen wird. Was ich nicht verstehe ist, wie wenn putStrLn
ein 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
.
helloworld
der 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 HelloWorld
Funktion, die bei jedem HelloWorld
Aufruf 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.
helloWorld
eine Konstante wie ein Feld oder eine Variable in C # vor. Es gibt keinen Parameter, auf den angewendet wirdhelloWorld
.