How does forever monad work?
forever :: (Monad m) => m a -> m b
forever a = a >> forever a
If I write
main = forever $ putStrLn "SAD, I DON'T UNDERSTAND!"
forever gets IO (), this isn't function, how can forever repeatedly call putStrLn?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With