
Daniel McAllansmith wrote:
When I try to add MonadError into the types I eventually hit the requirement for allow-undecidable-instances. Is there some way I can I avoid having to use this extension?
class (Num i, Bounded i, Monad m, MonadError String m) => MonadSource i m | m -> i where
The constraint |MonadError String m| that shows up in the class (and hence, eventually) instance context contains a type constant String. Such constraints indeed require 'allow-undecidable-instances'. It is possible to get around such requirement in some cases, by `shifting the blame (that is, the constraint)':
{-# OPTIONS -fglasgow-exts #-}
import Control.Monad import Control.Monad.Identity import Control.Monad.Trans import Control.Monad.Error import Control.Monad.State
class (Num i, Bounded i, Monad m) => MonadSource i m | m -> i where foo :: MonadError String m => m i
newtype SourceT i m a = SourceT (StateT i m a) deriving (Functor, Monad, MonadIO, MonadTrans, MonadError String)
runSourceT (SourceT m) = runStateT m 10
instance (Num i, Bounded i, Monad m) => MonadSource i (SourceT i m) where foo = if True then return 1 else throwError "error"
test :: Either String (Int,Int) = runIdentity . runErrorT . runSourceT $ foo