How does forever monad work?
forever :: (Monad m) => m a -> m b
forever a = a >> forever a
If I write
main =
From the definition of forever
function, you can see that it is a standard recursive function.
forever :: (Monad m) => m a -> m b
forever a = a >> forever a
There is no magic going on there. forever
is just a recursive function. In your particular case, this is a non terminating one. But whether it becomes a terminating or non terminating depends on how the Monad is defined for that type.
Inspect the type of >>
, we get:
λ> :t (>>)
(>>) :: Monad m => m a -> m b -> m b
From that you can observe the input m a
is just ignored. Another way to think about that is that >>
function just performs the side effect of the first parameter passed to it. In your case the m a
will correspond to IO ()
since that is the type of putStrLn
.
Since IO forms a Monad, forever
function can also act on IO
related functions.
The distinction to make is that putStrLn "SAD, I DON'T UNDERSTAND!"
is an action, not just a value. It repeatedly executes that action. Whenever something of type IO a
is evaluated, it executes its internal actions and then returns something of type a
wrapped in the IO
context. It doesn't have to take a parameter for the action to do something. For example, look at the getCurrentTime function from the time
package. It just has type IO UTCTime
, but if you call it several times you'll get different values back, even though it takes no parameters.