8

I'm trying to understand monad transformers by implementing my own tiny library based on the designs of existing ones.

What I'm stuck on is the language extensions. In MonadError, the only extension mentioned is UndecidableInstances. However, I can't get similar code to compile without also using FunctionalDependencies and FlexibleInstances.

Example that I believe requires FunDeps:

class (Monad m) => MonadError e m | m -> e where

And a flexible instance:

instance MonadError e m => MonadError e (MaybeT m) where

How does the MonadError code avoid the extra two extensions?

Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192

1 Answers1

11

You don't have to spell out all the extensions in the source file itself. Common extensions that are used by all/most modules can be listed in the project's cabal file. In mtl's case:

extensions:
    MultiParamTypeClasses
    FunctionalDependencies
    FlexibleInstances
shang
  • 24,642
  • 3
  • 58
  • 86
  • 7
    Note: You can do this, but many people prefer to spell out extensions with `LANGUAGE` pragmas in each file. That way files can be standalone and ghci-able, and it's easy to see what extensions each particular file is using, since you don't need to turn on every extension for every single file. It depends on which extensions you're using, and how pervasively. – shachaf Mar 01 '13 at 11:15
  • 1
    @shachaf: Absolutely. Good point. I, too, personally prefer to spell out every extension in every source file that uses them. – shang Mar 01 '13 at 11:19
  • 2
    Both is useful. I think the recommended approach should be to spell out extensions as needed per file using a `LANGUAGE` pragma, and to record the needed extensions for a package in Cabal's `other-extensions` field. The `other-extensions` list is not enabled by default, but it can still serve to understand what extension requirements a package has (without having to look at all source files individually). – kosmikus Mar 01 '13 at 13:54