`print <$> (print“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).
chi

답변:


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

모나드 법칙 덕분에

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상황에 특정한 것이 아니라 실제로 모나드를 유지한다고 덧붙였다.
leftaroundabout
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.