ทำไม `พิมพ์ <$> (พิมพ์“ hello”)` พิมพ์“ hello”


14

เมื่อทำการคำนวณIO (IO ())ทั้ง(IO ())และ()ถูกคำนวณแล้วทำไม

main :: IO (IO ())
main = print <$> (print "Hello, World!")

พิมพ์

"Hello, World!"

ไม่

IO "Hello, World!" -- ??
"Hello, World!"

3
โดยทั่วไปfmap print (print "Hello World")ใช้พารามิเตอร์แรกของมันที่ฟังก์ชั่นเพื่อผลมาจากการprint print "Hello World"นั่นเป็นเพียงการเรียกใช้print ()หลังจากprint "Hello World"ดำเนินการ
Redu

@Redu ถูกต้อง แต่โปรดทราบว่าการร้องขอprint ()ไม่เคยได้รับการประเมินหรือการดำเนินการของมัน (ซึ่งจะพิมพ์()บน stdout) ดังนั้น "การเรียกใช้print ()หลังจาก ... " จึงทำให้เข้าใจผิดเล็กน้อย (IMO)
ไค

คำตอบ:


21
main :: IO (IO ())
main = print <$> (print "Hello, World!")

ต้องขอบคุณกฎหมาย monad ที่

main :: IO (IO ())
main = do 
   result <- print "Hello, World!"
   return (print result)

ทีนี้ให้printผลตอบแทนกลับมาเสมอ()ดังนั้นรหัสทั้งหมดจึงเท่ากับ

main :: IO (IO ())
main = do 
   _ <- print "Hello, World!"
   return (print ())

ในที่สุดผลของการmainถูกทิ้งเพียง นั่นคือบรรทัดสุดท้ายอาจเป็นreturn (putStrLn "this is ignored")และมีผลเหมือนกัน

ดังนั้นรหัสจะดำเนินการครั้งแรกprint "Hello, World!"เท่านั้น

main :: IO ()ผมจะแนะนำให้คุณกำหนด Haskell ทำให้เราสามารถประกาศmain :: IO AnyTypeHereได้ แต่สิ่งนี้ (IMO) ทำให้เกิดความสับสน

ฉันอยากจะแนะนำให้คุณใช้putStrLnและไม่printต้องพิมพ์สตริงเนื่องจากหลังจะพูดและหลบหนีสตริงทั้งหมด


5
ฉันจะเพิ่มนั่นf <$> a ≡ a >>= \r -> return $ f rไม่ได้เป็นเพียงสิ่งที่เฉพาะเจาะจงกับสถานการณ์นี้ แต่จริง ๆ แล้วถือสำหรับ monad
leftaroundabout
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.