Recientemente, comencé a aprender Haskell porque quería ampliar mis conocimientos sobre programación funcional y debo decir que hasta ahora me encanta. El recurso que estoy usando actualmente es el curso 'Haskell Fundamentals Part 1' en Pluralsight. Desafortunadamente, tengo algunas dificultades para entender una cita particular del profesor sobre el siguiente código y esperaba que ustedes pudieran arrojar algo de luz sobre el tema.
Código de acompañamiento
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
La frase
Si tiene la misma acción IO varias veces en un do-block, se ejecutará varias veces. Entonces, este programa imprime la cadena 'Hola Mundo' tres veces. Este ejemplo ayuda a ilustrar que putStrLnno es una función con efectos secundarios. Llamamos a la putStrLnfunción una vez para definir la helloWorldvariable. Si putStrLntuviera un efecto secundario de imprimir la cadena, solo se imprimiría una vez y la helloWorldvariable repetida en el bloque principal no tendría ningún efecto.
En la mayoría de los otros lenguajes de programación, un programa como este imprimiría 'Hello World' solo una vez, ya que la impresión ocurriría cuando putStrLnse llamara a la función. Esta sutil distinción a menudo hace tropezar a los principiantes, así que piense un poco en esto y asegúrese de comprender por qué este programa imprime 'Hello World' tres veces y por qué lo imprimiría solo una vez si la putStrLnfunción imprimiera como un efecto secundario.
Lo que no entiendo
Para mí parece casi natural que la cadena 'Hello World' se imprima tres veces. Percibo la helloWorldvariable (¿o función?) Como una especie de devolución de llamada que se invoca más tarde. Lo que no entiendo es cómo si putStrLntuviera un efecto secundario, la cadena se imprimiría solo una vez. O por qué solo se imprimiría una vez en otros lenguajes de programación.
Digamos que en el código C #, supongo que se vería así:
C # (violín)
using System;
public class Program
{
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
public static void Main()
{
HelloWorld();
HelloWorld();
HelloWorld();
}
}
Estoy seguro de que estoy pasando por alto algo bastante simple o malinterpreto su terminología. Cualquier ayuda sería muy apreciada.
EDITAR:
¡Gracias a todos por sus respuestas o comentarios! Sus respuestas me ayudaron a comprender mejor estos conceptos. No creo que haya hecho clic completamente todavía, pero volveré a visitar el tema en el futuro, ¡gracias!
putStrLn no tiene un efecto secundario; simplemente devuelve una acción IO, la misma acción IO para el argumento, "Hello World"sin importar cuántas veces llame putStrLn.
helloworldno sería una acción que imprima Hello world; sería el valor devuelto por putStrLn después de lo impreso Hello World(a saber, ()).
helloWorld = Console.WriteLine("Hello World");. Simplemente contiene el Console.WriteLine("Hello World");en la HelloWorldfunción a ejecutar cada vez que HelloWorldse invoca. Ahora piensa en lo que helloWorld = putStrLn "Hello World"hace helloWorld. Se asigna a una mónada IO que contiene (). Una vez que lo vincula >>=, solo realizará su actividad (imprimiendo algo) y le dará ()en el lado derecho del operador de vinculación.
helloWorldser constante, como un campo o variable en C #. No hay ningún parámetro al que se esté aplicandohelloWorld.