haskell / mtl

The Monad Transformer Library
http://www.haskell.org/haskellwiki/Monad_Transformers
Other
362 stars 63 forks source link

instance (MonadError e f, MonadError e g) => MonadError e (Product f g) #84

Open LightAndLight opened 3 years ago

LightAndLight commented 3 years ago

Is there a technical reason why this instance doesn't exist? It seems well-behaved (some sanity-check proofs are at the bottom of the page).

fstP :: Product f g a -> f a
fstP (Pair a _) = a

sndP :: Product f g a -> g a
sndP (Pair _ a) = a

instance (MonadError e f, MonadError e g) => MonadError e (Product f g) where
  throwError e = Pair (throwError e) (throwError e)
  catchError (Pair ma mb) f = Pair (catchError ma (fstP . f)) (catchError mb (sndP . f))

catchError m throwError = m

catchError (Pair f g) throwError
= { inline catchError }
Pair (catchError f (fstP . throwError)) (catchError g (sndP . throwError))
= { inline throwError }
Pair 
  (catchError f (fstP . (\e -> Pair (throwError e) (throwError e)))
  (catchError g (sndP . (\e -> Pair (throwError e) (throwError e)))
= { inline (.) }
Pair 
  (catchError f (\e -> fstP (Pair (throwError e) (throwError e)))
  (catchError g (\e -> sndP (Pair (throwError e) (throwError e)))
= { eta-reduction }
Pair 
  (catchError f (\e -> throwError e))
  (catchError g (\e -> throwError e))
= { eta-reduction }
Pair 
  (catchError f throwError)
  (catchError g throwError)
= { hypothesis }
Pair f g
catchError (throwError e) pure = pure e

catchError (throwError e) pure
= { inline throwError }
catchError (Pair (throwError e) (throwError e)) pure = pure e
= { inline catchError }
Pair (catchError (throwError e) (fstP . pure)) (catchError (throwError e) (sndP . pure))
= { inline pure, (.) }
Pair 
  (catchError (throwError e) (\x -> fstP (Pair (pure x) (pure x)))) 
  (catchError (throwError e) (\x -> sndP (Pair (pure x) (pure x))))
= { eta-reduction }
Pair 
  (catchError (throwError e) (\x -> pure x)) 
  (catchError (throwError e) (\x -> pure x))
= { eta-reduction }
Pair 
  (catchError (throwError e) pure) 
  (catchError (throwError e) pure)
= { hypothesis }
Pair (pure e) (pure e}
= { pure }
pure e
despresc commented 3 years ago

Is that instance unnecessarily restrictive? I would have thought that

instance (MonadError e1 f, MonadError e2 g) => MonadError (e1, e2) (Product f g) where

would work as well. Your throwError would then be \e -> throwError (e, e).


EDIT: Never mind. The catchError method can't be defined with this alternate instance.