Reputation: 833
In the mtl
library, I see the definition of 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)
So writer
and tell
recursively calls each other. But I can't understand how that works. Is there a stop condition? Does this work because of the laziness of Haskell? Could anyone shine a light on it?
Upvotes: 0
Views: 61
Reputation: 43872
Note the MINIMAL
annotation:
{-# MINIMAL (writer | tell), listen, pass #-}
This tells GHC which class methods need to be implemented to make a complete instance. Normally, this set of methods is inferred by the compiler—it’s just the set of methods that don’t have default implementations—but in some situations, it’s useful to specify it explicitly. This is one such situation.
The MINIMAL
annotation for MonadWriter
says that listen
and pass
must always be implemented, and this makes sense, since those methods don’t have any default implementations. It then goes on to say something more interesting: either writer
or tell
must be implemented, but not necessarily both.
This works out, since if an instance supplies an implementation of writer
, then the default implementation for tell
will be used to implement it in terms of the provided writer
implementation. Likewise, the inverse will be true if an instance supplies tell
but not writer
. The MINIMAL
annotation protects an instance from supplying an implementation of neither, so no complete instance can ever have both default implementations in use at once.
Upvotes: 11