Ths is a perfect use case for DerivingVia
(it was brought to my attention that I didn't read the question carefully enough, you have to use a newtype
one way or the other: this solution is not what you were hoping for but it is idiomatic)
{-# Language DerivingVia #-}
{-# Language StandaloneKindSignatures #-}
import Control.Applicative (Alternative)
import Control.Monad (MonadPlus)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans.Maybe
import Control.Monad.Zip (MonadZip)
import Data.Kind (Type)
type Fortunate :: Type -> Type
newtype Fortunate a = Fortunate [Maybe a]
deriving
( Functor, Foldable, Applicative, Alternative
, Monad, MonadPlus, MonadFail, MonadFix, MonadZip
)
via MaybeT []
Some of these instances like (Functor, Foldable, Applicative, Alternative)
can be derived via Compose Maybe []
.
To list what instances can be derived, use the :instances
command
>> :instances MaybeT []
instance [safe] Alternative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Applicative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
...
>> :instances Compose Maybe []
instance Alternative (Compose Maybe [])
-- Defined in ‘Data.Functor.Compose’
instance Applicative (Compose Maybe [])
-- Defined in ‘Data.Functor.Compose’
...
Because Fortunate
is an applicative you can derive (Semigroup, Monoid, Num, Bounded)
through pointwise (idiomatic, applicative) lifting:
import Data.Monoid (Ap(..))
..
deriving (Semigroup, Monoid, Num, Bounded)
via Ap Fortunate a
where (<>) = liftA2 (<>)
, abs = liftA abs
, mempty = pure mempty
, minBound = pure minBound
.