`` <$> [Baskı “merhaba”) neden “merhaba” yazdırıyor?


14

Hesaplarken IO (IO ()), hem (IO ())ve hem de ()hesaplanır, bu yüzden neden

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

Yazdır

"Hello, World!"

değil

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

3
Temelde fmap print (print "Hello World"), ilk parametre olan printişlevi sonucuna uygular print "Hello World". Bu, eylem gerçekleştirildikten print ()sonra çağırmanın eşdeğeridir print "Hello World".
Redu

@Redu Bu doğrudur, ancak print ()hiçbir zaman çağrılmayacağını veya eyleminin gerçekleştirilmediğine dikkat edin ( ()stdout'a yazdıracaktır ). Yani, " print ()sonra çağırmak ..." biraz yanıltıcıdır (IMO).
chi

Yanıtlar:


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

monad yasaları sayesinde

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

Şimdi, printher zaman ()sonuç olarak döner , bu nedenle tüm kod

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

Son olarak, sonucu mainbasitçe atılır. Yani, son satır return (putStrLn "this is ignored")aynı etkiye sahip olabilir ve aynı etkiye sahip olabilir .

Bu nedenle kod yalnızca ilkini yürütür print "Hello, World!".

Her zaman tanımlamanızı tavsiye ederim main :: IO (). Haskell bildirmemize izin veriyor main :: IO AnyTypeHere, ama bu (IMO) kafa karıştırıcı.

Ayrıca putStrLn, printdizeyi yazdırmamanızı da öneririz , çünkü ikincisi tüm dizeyi alıntılayıp kaçacaktır.


5
f <$> a ≡ a >>= \r -> return $ f rBu duruma sadece belirli bir şey değil, aynı zamanda herhangi bir monad için de geçerli olduğunu ekleyeceğim .
leftaroundabout
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.