Haskell 2010 Report (the language definition) says:
The value of the program is the value of the identifier main
in module
Main
, which must be a computation of type IO τ
for some type τ
.
When the program is executed, the computation main
is
performed, and its result (of type τ
) is discarded.
Your main
function has type IO (IO ())
. The quote above means that only the outer action (IO (IO ())
) is evaluated, and its result (IO ()
) is discarded. How did you get here? Let's look at the type of print <$>
:
> :t (print <$>)
(print <$>) :: (Show a, Functor f) => f a -> f (IO ())
So the problem is that you used fmap
in conjunction with print
. Looking at the definition of Functor
instance for IO
:
instance Functor IO where
fmap f x = x >>= (return . f)
you can see that that made your expression equivalent to (head <$> getArgs >>= return . print)
. To do what you originally intended, just remove the unnecessary return
:
head <$> getArgs >>= print
Or, equivalently:
print =<< head <$> getArgs
Note that IO actions in Haskell are just like other values - they can be passed to and returned from functions, stored in lists and other data structures, etc. An IO action is not evaluated unless it's a part of the main computation. To "glue" IO actions together, use >>
and >>=
, not fmap
(which is typically used for mapping pure functions over values in some "box" - in your case, IO
).
Note also that this has to do not with lazy evaluation, but purity - semantically, your program is a pure function that returns a value of type IO a
, which is then interpreted by the runtime system. Since your inner IO
action is not part of this computation, the runtime system just discards it. A nice introduction to these issues is the second chapter of Simon Peyton Jones's "Tackling the Awkward Squad".