Có hai điều đang diễn ra tại đây.
Đầu tiên, hãy xem xét
let x = sum [1..1000000] in 42
Haskell là lười biếng. Vì chúng tôi không thực sự làm bất cứ điều gì với x
, nó không bao giờ được tính toán. Thật vậy, vì nó sẽ hơi chậm.) Thật vậy, nếu bạn biên dịch điều này, trình biên dịch sẽ thấy rằng x
không bao giờ được sử dụng và xóa nó (tức là, không tạo ra bất kỳ mã được biên dịch nào cho nó).
Thứ hai, gọi putStrLn
không thực sự in bất kỳ thứ gì. Thay vào đó, nó trả về IO()
, mà bạn có thể nghĩ là một loại "đối tượng lệnh I/O". Chỉ có một đối tượng lệnh khác với việc thực hiện đối tượng đó. Theo thiết kế, cách duy nhất để "thực hiện" một đối tượng lệnh I/O là trả về nó từ main
. Ít nhất, nó nằm trong một chương trình hoàn chỉnh; GHCi có tính năng hữu ích nếu bạn nhập một biểu thức trả về một đối tượng lệnh I/O, GHCi sẽ thực thi nó cho bạn.
Biểu thức của bạn trả về 42; một lần nữa, f
không được sử dụng, do đó, nó không làm bất cứ điều gì.
Là chi
đúng chỉ ra, nó giống như tuyên bố một hàm cục bộ (không đối số) nhưng không bao giờ gọi nó. Bạn sẽ không mong đợi để xem bất kỳ đầu ra.
Bạn cũng có thể làm điều gì đó như
actions = [print 5, print 6, print 7, print 8]
Điều này tạo ra một danh sách các đối tượng tôi/O lệnh. Nhưng, một lần nữa, nó không thực hiện bất kỳ trong số chúng.
Thông thường, khi bạn viết một hàm có I/O, đó là một khối lệnh chặn mọi thứ vào một đối tượng lệnh I/O khổng lồ và trả về cho người gọi. Trong trường hợp đó, bạn thực sự không cần phải hiểu hay không về sự khác biệt này giữa xác định đối tượng lệnh và thực hiện. Nhưng sự khác biệt vẫn còn đó.
Có thể dễ dàng thấy điều này hơn với một đơn vị có chức năng chạy rõ ràng. Ví dụ: runST
lấy đối tượng lệnh ST, chạy đối tượng đó và cung cấp cho bạn câu trả lời. Nhưng (nói) newSTVar
, tự nó không làm gì ngoài việc xây dựng một lệnh ST; bạn phải runST
trước khi bất cứ điều gì thực sự "xảy ra".
Bạn có thể muốn đọc về ['let' vs' <-'] (http://stackoverflow.com/q/28624408/3234959). Nó không phải là vấn đề chính xác bạn đang có bây giờ, nhưng nó có thể giúp đỡ. – chi
Đọc [Tại sao tôi không thể ép buộc hành động IO với seq?] (Http://stackoverflow.com/q/20324446/510937) để biết thêm thông tin về đánh giá và thực thi các hành động IO. – Bakuriu