Why does importing Control.Applicative allow this bad code to type check?

前端 未结 2 1482
滥情空心
滥情空心 2020-12-19 01:43

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.

相关标签:
2条回答
  • 2020-12-19 02:15

    There isn't an instance for (->) String, but there is an instance for (->) e... and that instance is very, very useful in many situations. For the second question, we must take a look at forever and the class instance for functions:

    instance Monad ((->) e) where
        return x = \e -> x
        m >>= f  = \e -> f (m e) e
    
    forever m = m >> forever m = m >>= \_ -> forever m
    

    Now, what does forever putStrLn do?

    forever putStrLn
        = putStrLn >>= \_ -> forever putStrLn
        = \e -> (\_ -> forever putStrLn) (putStrLn e) e
        = \e -> (forever putStrLn) e
        = forever putStrLn
    

    ...it's just a pure infinite loop, basically identical to loop = loop.

    To get some intuition for what's going on with the reader monad (as it is known), take a look at the documentation, the All About Monads section on Reader, and there are some hints sprinkled throughout the Typeclassopedia which might help.

    0 讨论(0)
  • 2020-12-19 02:15

    Control.Applicative imports Control.Monad.Instances, and therefore re-exports the instances from Control.Monad.Instances. This includes Functor and Monad instances for ((->) r).

    0 讨论(0)
提交回复
热议问题