views:

235

answers:

2

I can't figure out what the "| m -> w"-part means in a class definition like this:

class (Monoid w, Monad m) => MonadWriter w m | m -> w

What additional information does this add to the class definition?

+5  A: 

It specifies a functional dependency.

sepp2k
+12  A: 

The vertical bar is a syntactic separator with no meaning itself, used to introduce functional dependencies on a multi-parameter type class, so technically | means nothing whatsoever. Presumably | was chosen as a visual analogy to the same symbol's use for pattern guards on functions.

As far as the functional dependencies themselves go, just read x -> y as "type parameter x uniquely determines type parameter y", meaning that knowing x alone is sufficient to find the correct instance. There are further complications, especially with other GHC extensions enabled, but most of the time you don't need to worry about them.

In contrast, without functional dependencies, selecting an instance of a multi-parameter type class requires that all type parameters be known. A typical example has one parameter being a container type and a second being the type of the contained elements; functions such as "concatenate" or "isEmpty" need not mention the element type, only the container type, and thus would be ambiguous.

Also, if you're writing your own type classes, consider instead using type families, which are a new approach that may eventually replace functional dependencies. Roughly speaking, type families let you write overloaded type definitions inside an instance, not just overloaded functions.

camccann
Great answer, thanks a lot! Nice link, too! Got to look into that type family thing once I finished figuring out how these Monad Transformers work...
martingw
@martingw: If you ask me, type families are *much* more pleasant than monad transformers, which seem like an ugly hack, albeit a useful one. Though if you want, there's a package `monads-tf` that implements the standard transformers with type families instead of functional dependencies: http://hackage.haskell.org/package/monads-tf
camccann