Perché `print <$> (stampa“ ciao ”)` stampa “ciao”?


14

Nel calcolo IO (IO ()), sia (IO ())e() viene calcolato, quindi perché

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

Stampa

"Hello, World!"

non

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

3
Fondamentalmente fmap print (print "Hello World")applica il suo primo parametro, la printfunzione, al risultato di print "Hello World". Questo è semplicemente l'equivalente di invocare print ()dopo l' print "Hello World"esecuzione dell'azione.
Redu,

@Redu È corretto, ma nota che l'invocazione di print ()non viene mai valutata, né la sua azione eseguita (che verrebbe stampata ()su stdout). Quindi, "invocare print ()dopo ..." è un po 'fuorviante (IMO).
chi,

Risposte:


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

è equivalente, grazie alle leggi della monade, a

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

Adesso, print restituisce sempre ()come risultato, quindi l'intero codice è equivalente a

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

Infine, il risultato di mainviene semplicemente scartato. Cioè, l'ultima riga potrebbe essere return (putStrLn "this is ignored")e avere lo stesso effetto.

Quindi il codice eseguirà solo il primo print "Hello, World!".

Consiglierei di definire sempre main :: IO () . Haskell ci permette di dichiarare main :: IO AnyTypeHere, ma questo è (IMO) confuso.

Consiglierei anche di usare putStrLn, e non printdi stampare le stringhe, poiché quest'ultima citerà e sfuggirà all'intera stringa.


5
Aggiungerei che f <$> a ≡ a >>= \r -> return $ f rnon è solo una cosa specifica in questa situazione, ma in realtà vale per qualsiasi monade.
lasciato il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.