r/haskell•
mallai

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

415
Loading comments…