Explicitly import instances

How do I explicitly import typeclass instances? Also, how do I do this with a qualified import?

Currently, I'm doing

import Control.Monad.Error ()

to import the monad instance that I can use for (Either String). Previously, I used

import Control.Monad.Error

I'm not satisfied with either one, because the Monad instance is implicitly imported.


Solution 1:

The inability to control imports of instances is one of the trade-offs the Haskell typeclass system makes. Here's an example in a hypothetical Haskell dialect where you can:

Foo.hs:

module Foo where

data Foo = FooA | FooB deriving (Eq, Ord)

Bar.hs:

module Bar (myMap) where

import Data.Map (Map)
import qualified Data.Map as Map

import Foo

myMap :: Map Foo Int
myMap = Map.singleton FooA 42

Baz.hs:

module Baz where

import Data.Map (Map)
import qualified Data.Map as Map

import Foo hiding (instance Ord Foo)
import Bar (myMap)

instance Ord Foo where
  FooA > FooB = True
  FooB > FooA = False

ouch :: Map Foo Int
ouch = Map.insert FooB 42 myMap

Yikes! The set myMap was created with the proper instance Ord Foo, but it's being combined with a map created with a different, contradictory instance.

Being able to do this would violate Haskell's open world assumption. Unfortunately, I don't know of a good, centralised resource for learning about it. This section of RWH might be helpful (I searched for "haskell open world assumption").

Solution 2:

You can't. Instances are always implicitly exported and hence you can't explicitly import them. By the way, Either e's Monad instance is nowadays in Control.Monad.Instances.

Solution 3:

Although the generally correct answer would be "no, you can't", I suggest this horrendous solution:

copy + paste

Take a look at the library source code for the desired module, and copy/paste the necessary data declarations, imports, and function definitions into your own code. Don't copy the instances you don't want.

Depending on the problem at hand, the ghc type system extensions OverlappingInstances or IncoherentInstances might be an alternate solution, though this probably won't solve any problems with the base libraries.