I feel the DerivingVia extension gives new life to this kind of shell of a new type. Suppose, for some reason, we want to write Monad and MonadPlus for a type, and then add them for Applicative and Alternative :
newtype StT sma = StT { runStT :: s -> m (a, s) } deriving Functor instance Monad m => Monad (StT sm) where return a = StT $ \s -> return (a, s) m >>= f = StT $ \s -> m 'runStT' s >>= \(a, t) -> fa 'runStT' t instance MonadPlus m => MonadPlus (StT sm) where mzero = StT $ \_ -> mzero m 'mplus' n = StT $ \s -> (m 'runStT' s) 'mplus' (n 'runStT' s)
Usually we would have to write sample examples:
instance Monad m => Applicative (StT sm) where pure = return (<*>) = ap instance MonadPlus m => Alternative (StT sm) where empty = mzero (<|>) = mplus
With DerivingVia , WrappedMonad you can use his spell in a way that, in my eyes, is much better.
newtype StT sma = StT { runStT :: s -> m (a, s) } deriving Functor deriving (Applicative, Alternative) via WrappedMonad (StT sm)
Please note that pre-existing derivative offers are not affected. Another nice point is that the necessary restrictions of the superclass are deduced.
source share