I'm helping a friend learn Haskell and he recently created code like this, which type checks and produces a CPU-burning loop at runtime. I'm completely baffled by this.
import Control.Monad
import Control.Applicative
main = forever putStrLn "Hello, infinity"
That shouldn't type check, but does. The correct version would clearly be:
main = forever $ putStrLn "Hello, infinity"
What's weird and surprising to me is that you get different results with and without importing Control.Applicative. Without importing it, it doesn't type check:
Prelude Control.Monad> forever putStrLn "Hello, infinity"
<interactive>:1:1:
No instance for (Monad ((->) String))
arising from a use of `forever'
Possible fix: add an instance declaration for (Monad ((->) String))
In the expression: forever putStrLn "Hello, infinity"
In an equation for `it': it = forever putStrLn "Hello, infinity"
I don't see a Monad instance for ((->) String
in the source for Control.Applicative, so I'm guessing something weird is happening due to its use of Control.Category or Control.Arrow, but I don't know. So I guess I have two questions:
- What is it about importing Control.Applicative that lets this happen?
- What's happening when it enters the infinite loop? What is Haskell actually trying to execute in that case?
Thanks,
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…