Récemment, j'ai commencé à apprendre Haskell parce que je voulais élargir mes connaissances sur la programmation fonctionnelle et je dois dire que je l'aime vraiment jusqu'à présent. La ressource que j'utilise actuellement est le cours «Haskell Fundamentals Part 1» sur Pluralsight. Malheureusement, j'ai du mal à comprendre une citation particulière du conférencier au sujet du code suivant et j'espérais que vous pourriez éclairer le sujet.
Code d'accompagnement
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
    helloWorld
    helloWorld
    helloWorld
La citation
Si vous avez la même action IO plusieurs fois dans un do-block, elle sera exécutée plusieurs fois. Ce programme imprime donc la chaîne «Hello World» trois fois. Cet exemple permet d'illustrer que ce putStrLnn'est pas une fonction avec des effets secondaires. Nous appelons la putStrLnfonction une fois pour définir la helloWorldvariable. Si cela putStrLnavait pour effet secondaire d'imprimer la chaîne, elle ne s'imprimerait qu'une seule fois et la helloWorldvariable répétée dans le do-block principal n'aurait aucun effet.
Dans la plupart des autres langages de programmation, un programme comme celui-ci n'imprimait 'Hello World' qu'une seule fois, car l'impression se produisait lorsque la putStrLnfonction était appelée. Cette distinction subtile ferait souvent trébucher les débutants, alors pensez-y un peu et assurez-vous de comprendre pourquoi ce programme imprime `` Hello World '' trois fois et pourquoi il ne l'imprimerait qu'une seule fois si la putStrLnfonction faisait l'impression comme effet secondaire.
Ce que je ne comprends pas
Pour moi, il semble presque naturel que la chaîne «Hello World» soit imprimée trois fois. Je perçois la helloWorldvariable (ou la fonction?) Comme une sorte de rappel qui est invoqué plus tard. Ce que je ne comprends pas, c'est que si cela putStrLnavait un effet secondaire, cela entraînerait l'impression de la chaîne une seule fois. Ou pourquoi il ne serait imprimé qu'une seule fois dans d'autres langages de programmation.
Disons que dans le code C #, je suppose que cela ressemblerait à ceci:
C # (violon)
using System;
public class Program
{
    public static void HelloWorld()
    {
        Console.WriteLine("Hello World");
    }
    public static void Main()
    {
        HelloWorld();
        HelloWorld();
        HelloWorld();
    }
}
Je suis sûr que j'oublie quelque chose d'assez simple ou que je interprète mal sa terminologie. Toute aide serait grandement appréciée.
ÉDITER:
Merci à tous pour vos réponses! Vos réponses m'ont aidé à mieux comprendre ces concepts. Je ne pense pas qu'il ait complètement cliqué pour le moment, mais je reviendrai sur le sujet à l'avenir, merci!
putStrLn n'a pas d'effet secondaire; il renvoie simplement une action IO, la même action IO pour l'argument, "Hello World"quel que soit le nombre de fois que vous appelez putStrLn.
                helloworldserait pas une action qui s'imprime Hello world; ce serait la valeur renvoyée par putStrLn après  son impression Hello World(à savoir, ()).
                helloWorld = Console.WriteLine("Hello World");. Vous venez de contenir la Console.WriteLine("Hello World");dans la HelloWorldfonction à exécuter chaque fois que vous HelloWorldinvoquez. Pensez maintenant à ce qui helloWorld = putStrLn "Hello World"fait helloWorld. Il est affecté à une monade IO qui contient (). Une fois que vous le lierez, il >>=effectuera seulement son activité (impression de quelque chose) et vous donnera ()sur le côté droit de l'opérateur de liaison.
                
helloWorldêtre constant comme un champ ou une variable en C #. Aucun paramètre n'est appliquéhelloWorld.