module Either where import Control.Monad (liftM) import MonadTrans import MonadIO newtype EitherT e m a = EitherT { runEitherT :: m (Either e a) } -- 1 instance Functor m => Functor (EitherT e m) where fmap f (EitherT x) = EitherT $ (fmap . fmap) f x -- 2 instance Applicative m => Applicative (EitherT e m) where pure x = EitherT $ pure $ pure x (EitherT f) <*> (EitherT a) = EitherT $ (<*>) <$> f <*> a -- 3 instance Monad m => Monad (EitherT e m) where return = pure (EitherT em) >>= f = EitherT $ do v <- em case v of Left y -> return $ Left y Right y -> runEitherT (f y) -- 4 -- transformer version of swapEither. -- Hint: write swapEither first, then swapEitherT in terms of the former. swapEither :: Either e a -> Either a e swapEither (Left x) = Right x swapEither (Right y) = Left y swapEitherT :: (Functor m) => EitherT e m a -> EitherT a m e swapEitherT (EitherT x) = EitherT $ fmap swapEither x -- 5. Write the transformer variant of the either catamorphism. eitherT :: Monad m => (a -> m c) -> (b -> m c) -> EitherT a m b -> m c eitherT f g (EitherT x) = x >>= (either f g) instance MonadTrans (EitherT e) where lift = EitherT . liftM Right instance (MonadIO m) => MonadIO (EitherT e m) where liftIO = lift . liftIO