เมื่อเร็ว ๆ นี้ฉันเริ่มเรียนรู้ Haskell เพราะฉันต้องการที่จะขยายความรู้ของฉันในการเขียนโปรแกรมฟังก์ชั่นและฉันต้องบอกว่าฉันรักมันจริงๆ ทรัพยากรที่ฉันใช้อยู่ในขณะนี้คือ 'Haskell Fundamentals Part 1' บน Pluralsight น่าเสียดายที่ฉันมีปัญหาในการทำความเข้าใจคำพูดหนึ่งของอาจารย์ผู้สอนเกี่ยวกับรหัสต่อไปนี้และหวังว่าพวกคุณจะเข้าใจในหัวข้อนี้
รหัสที่มาพร้อมกับ
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
อ้าง
หากคุณมีการกระทำ IO เดียวกันหลายครั้งใน do-block มันจะถูกเรียกใช้หลายครั้ง ดังนั้นโปรแกรมนี้พิมพ์สตริง '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
จะได้รับมอบหมายให้ monad IO ()
ซึ่งประกอบด้วย เมื่อคุณผูกมันแล้วมัน>>=
ก็จะทำกิจกรรมของมัน (การพิมพ์บางอย่าง) และจะให้()
ทางด้านขวาของผู้ประกอบการผูก
helloWorld
คงที่เช่นเขตข้อมูลหรือตัวแปรใน C #helloWorld
มีพารามิเตอร์ไม่มีที่จะถูกนำไปใช้เป็น