Gần đây, tôi bắt đầu học Haskell vì tôi muốn mở rộng kiến thức về lập trình chức năng và tôi phải nói rằng tôi thực sự yêu thích nó cho đến nay. Tài nguyên tôi hiện đang sử dụng là khóa học 'Haskell Fund basicals Part 1' về Pluralsight. Thật không may, tôi có một số khó khăn để hiểu một trích dẫn cụ thể của giảng viên về mã sau đây và hy vọng các bạn có thể làm sáng tỏ chủ đề này.
Mã kèm theo
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
Trích dẫn
Nếu bạn có cùng một hành động IO nhiều lần trong một khối do, nó sẽ được chạy nhiều lần. Vì vậy, chương trình này in ra chuỗi 'Hello World' ba lần. Ví dụ này giúp minh họa rằng đó putStrLn
không phải là một chức năng với các tác dụng phụ. Chúng ta gọi putStrLn
hàm một lần để xác định helloWorld
biến. Nếu putStrLn
có tác dụng phụ là in chuỗi, nó sẽ chỉ in một lần và helloWorld
biến được lặp lại trong khối do chính sẽ không có tác dụng.
Trong hầu hết các ngôn ngữ lập trình khác, một chương trình như thế này sẽ chỉ in 'Hello World' một lần, vì việc in sẽ xảy ra khi putStrLn
chức năng được gọi. Sự khác biệt tinh tế này thường làm vấp ngã những người mới bắt đầu, vì vậy hãy suy nghĩ về điều này một chút và đảm bảo bạn hiểu lý do tại sao chương trình này in 'Hello World' ba lần và tại sao nó chỉ in một lần nếu putStrLn
chức năng in là hiệu ứng phụ.
Những gì tôi không hiểu
Đối với tôi, dường như gần như tự nhiên rằng chuỗi 'Hello World' được in ba lần. Tôi cảm nhận helloWorld
biến (hoặc hàm?) Như một kiểu gọi lại được gọi sau này. Điều tôi không hiểu là, làm thế nào nếu putStrLn
có tác dụng phụ, nó sẽ dẫn đến chuỗi chỉ được in một lần. Hoặc tại sao nó chỉ được in một lần bằng các ngôn ngữ lập trình khác.
Giả sử trong mã C #, tôi sẽ cho rằng nó sẽ trông như thế này:
C # (Câu đố)
using System;
public class Program
{
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
public static void Main()
{
HelloWorld();
HelloWorld();
HelloWorld();
}
}
Tôi chắc chắn rằng tôi đang xem xét một cái gì đó khá đơn giản hoặc giải thích sai thuật ngữ của anh ấy. Mọi sự trợ giúp sẽ rất được trân trọng.
BIÊN TẬP:
Cảm ơn tất cả các câu trả lời của bạn! Câu trả lời của bạn đã giúp tôi hiểu rõ hơn về các khái niệm này. Tôi không nghĩ rằng nó đã được nhấp hoàn toàn, nhưng tôi sẽ xem lại chủ đề trong tương lai, cảm ơn bạn!
putStrLn
không có tác dụng phụ; nó chỉ đơn giản trả về một hành động IO, hành động IO tương tự cho đối số cho "Hello World"
dù bạn gọi bao nhiêu lần putStrLn
.
helloworld
sẽ không phải là một hành động in Hello world
; nó sẽ là giá trị trả về bởi putStrLn
sau khi nó được in Hello World
(cụ thể là, ()
).
helloWorld = Console.WriteLine("Hello World");
. Bạn chỉ chứa hàm Console.WriteLine("Hello World");
trong HelloWorld
hàm được thực thi mỗi khi HelloWorld
được gọi. Bây giờ nghĩ về những gì helloWorld = putStrLn "Hello World"
làm cho helloWorld
. Nó được gán cho một đơn vị IO có chứa ()
. Khi bạn liên kết nó, >>=
nó sẽ chỉ thực hiện hoạt động của nó (in một cái gì đó) và sẽ cung cấp cho bạn ()
ở phía bên phải của toán tử liên kết.
helloWorld
hằng số như một trường hoặc biến trong C #. Không có tham số nào đang được áp dụnghelloWorld
.