最近,我开始学习Haskell,因为我想扩大我对函数式编程的了解,我必须说到目前为止我真的很喜欢它。我当前使用的资源是Pluralsight上的“ Haskell基础知识第1部分”课程。不幸的是,我在理解讲师关于以下代码的一句话时遇到了一些困难,希望你们能对此话题有所了解。
随附代码
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
报价单
如果您在一个do块中多次执行相同的IO操作,则它将多次运行。因此,该程序将字符串“ Hello World”输出三遍。本示例有助于说明这putStrLn
不是具有副作用的功能。我们只调用putStrLn
一次函数来定义helloWorld
变量。如果putStrLn
有打印字符串的副作用,它将只打印一次,并且helloWorld
在主do-block中重复的变量将没有任何效果。
在大多数其他编程语言中,这样的程序只会打印一次“ Hello World”,因为在putStrLn
调用函数时会进行打印。这种微妙的区别通常会使初学者不胜其烦,因此请仔细考虑一下,并确保您了解为什么该程序会打印“ Hello World”三遍,以及如果该putStrLn
函数作为副作用打印时只打印一次。
我不明白的
对我来说,字符串“ Hello World”被打印三遍似乎是很自然的。我认为helloWorld
变量(或函数?)是一种稍后调用的回调。我不明白的是,如果putStrLn
产生副作用,它将导致字符串仅打印一次。或者为什么只用其他编程语言只打印一次。
假设在C#代码中,我想它看起来像这样:
C# (提琴)
using System;
public class Program
{
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
public static void Main()
{
HelloWorld();
HelloWorld();
HelloWorld();
}
}
我确信我会忽略一些很简单的东西,或者会误解他的术语。任何帮助将不胜感激。
编辑:
谢谢大家的答案!您的回答使我对这些概念有了更好的理解。我认为尚未完全点击,但以后我将重新讨论该主题,谢谢!
putStrLn
没有副作用;它只是返回一个IO操作,无论调用多少次,该参数都将执行相同的 IO操作。"Hello World"
putStrLn
helloworld
将不是一个打印出来的动作Hello world
;这将是由返回的值putStrLn
后 它印刷Hello World
(即,()
)。
helloWorld = Console.WriteLine("Hello World");
。您只需Console.WriteLine("Hello World");
在HelloWorld
每次HelloWorld
调用要执行的函数中包含。现在想想是什么helloWorld = putStrLn "Hello World"
让helloWorld
。它被分配给包含的IO monad ()
。一旦绑定它,>>=
它将仅执行它的活动(打印一些内容),并()
在bind运算符的右侧。
helloWorld
常量,例如C#中的字段或变量。没有适用于的参数helloWorld
。