Why can't Haskell be tricked into performing IO operations by using strict evaluation?
haskell, io-monad, monads
Solution
The expression you are forcing is `((print "hi") >>= (\r -> return ()))`, which is of type `IO ()`. As such it represents an IO action. But evaluating such a thing is quite different from running it!
Evaluating a value means performing just enough steps to turn it into what is called weak head normal form. Because `IO` is abstract, it is a bit tricky to see what that means in this case, but one can think of `IO a` as `RealWorld -> (a, RealWorld)`, and then the weak head normal form is, well, a function waiting to be given the `RealWorld`.
Running implies evaluation, but also passes the `RealWorld` as an argument, thus causing the `IO` effect to happen.
All this is not very specific to `IO`; your confusion and the concepts apply equally to `a -> b`. If you understand what `$!` does when the second argument is a function, you’ll understand what happens when it is an IO action.
Problem
I'm just learning Haskell and IO monads. I'm wondering why wouldn't this force the program to output "hi" as well as "bye": ``` second a b = b main = print ((second $! ((print "hi") >>= (\r -> return ()))) "bye") ``` As far as I understand, the `$!` operator would force the first argument of `second` to be evaluated, and the `>>=` operator would need to run `print "hi"` in order to get a value off of it and pass it to `\r -> return ()`, which would print "hi" to the screen. What's wrong with my reasoning? And also, is there any way to proove Haskell cannot be tricked (other than using unsafe functions) into running IO operations inside "safe" code?