在mtl
库中,我看到了MonadWriter
的定义:
class (Monoid w, Monad m) => MonadWriter w m | m -> w where
#if __GLASGOW_HASKELL__ >= 707
{-# MINIMAL (writer | tell), listen, pass #-}
#endif
-- | @'writer' (a,w)@ embeds a simple writer action.
writer :: (a,w) -> m a
writer ~(a, w) = do
tell w
return a
-- | @'tell' w@ is an action that produces the output @w@.
tell :: w -> m ()
tell w = writer ((),w)
因此writer
和tell
互相递归调用。但是我不明白那是怎么回事。是否有停止条件?这是因为Haskell的惰性吗?有人可以照亮它吗?
答案 0 :(得分:11)
{-# MINIMAL (writer | tell), listen, pass #-}
这告诉GHC需要使用哪些类方法来构成完整的实例。通常,这组方法是由编译器推断的-只是没有默认实现的方法集-但在某些情况下,明确指定它很有用。这种情况就是这样。
MINIMAL
的{{1}}注释表示必须始终实现MonadWriter
和listen
,这是有道理的,因为这些方法没有任何默认实现。然后继续说一些更有趣的事情:pass
或 writer
必须实现,但不一定要同时实现。
这是可行的,因为如果实例提供了tell
的实现,那么就提供的writer
而言,将使用tell
的默认实现来实现它。同样,如果实例提供writer
但不提供tell
,则反之亦然。 writer
批注可保护实例避免提供都不的实现,因此,没有一个完整的实例可以同时使用这两个默认实现。