Depending on both mtl-2.1.3.1 for stackage LTS-2.* and mtl-2.2.1 for stackage nightly
At some point I moved my code to use the new ExceptT introduced in mtl-2.2. It's great, I can use GHC 7.10.2 and stackage nightly. But I can no longer use 7.8.4 and stackage LTS-2.22, because it has the old mtl-2.1.3.1 with the now deprecated ErrorT. Also, Hackage still uses 7.8.3 and I am getting build failures and no documentation.
So I came up with the following way of depending on both mtls using CPP (of course... :-( ).
First, extension
{-# LANGUAGE CPP #-}
Then, for imports
#if MIN_VERSION_mtl(2,2,0)
import Control.Monad.Except
#else
import Control.Monad.Error
#endif
Then, because my code was rewritten to use ExceptT everywhere, I introduced the type synonym and following functions:
#if !MIN_VERSION_mtl(2,2,0)
type ExceptT = ErrorT -- so that I don't have to fix all type signatures
runExceptT :: forall e (m :: * -> *) a. ErrorT e m a -> m (Either e a)
runExceptT = runErrorT -- so that I don't have to fix code
mkExceptT = ErrorT
#else
mkExceptT = ExceptT
#endif
Now, the problem starts with trying to give a type signature for runExceptT. That required adding {-# LANGUAGE RankNTypes, KindSignatures #-}, which is ok.
Another problem is with constructor. Wherever the constructor was used to create a valueExceptT ....., I had to replace it with mkExceptT. That's not too bad. However, wherever the constructor was used in a pattern match position, mkExceptT cannot be used.
So, the main question is:
How can I give an alias to the constructor the same way as I gave an alias to the type? I cannot declare a top-level constructor outside of the data definition like this:
ExceptT = ErrorT
Are there any better ways of dealing with such a problem?
Posted Aug 12, 2015, 5:00 PM UTC · edited