永远的monad如何工作?

时间:2014-06-04 16:39:50

标签: haskell

永远的monad如何运作?

forever :: (Monad m) => m a -> m b
forever a = a >> forever a

如果我写

main = forever $ putStrLn "SAD, I DON'T UNDERSTAND!"

永远得到IO(),这不是函数,怎么能永远反复调用putStrLn?

2 个答案:

答案 0 :(得分:11)

forever函数的定义,您可以看到它是一个标准的递归函数。

forever :: (Monad m) => m a -> m b
forever a = a >> forever a

那里没有魔法。 forever只是一个递归函数。在您的特定情况下,这是一个非终止的。但是它是终止还是非终止取决于如何为该类型定义Monad。

检查>>的类型,我们得到:

λ> :t (>>)
(>>) :: Monad m => m a -> m b -> m b

从中你可以看到输入m a被忽略了。另一种思考方式是>>函数只执行传递给它的第一个参数的副作用。在您的情况下,m a将与IO ()对应,因为这是putStrLn的类型。

由于IO形成Monad,forever函数也可以作用于IO相关函数。

答案 1 :(得分:3)

要做的区别是putStrLn "SAD, I DON'T UNDERSTAND!"动作,而不仅仅是一个值。它重复执行动作。每当评估IO a类型的某些内容时,它会执行其内部操作,然后返回包含在a上下文中的IO类型的内容。它不必为动作采取参数来做某事。例如,查看time包中的getCurrentTime函数。它只有IO UTCTime类型,但如果你多次调用它,你会得到不同的值,即使它没有参数。