(forall a . Evaluation a)
no tiene mucho sentido: eso significaría que cada solo tipo (incluyendo cualquier tipo de futuro que alguien podría hacer) era una instancia de Evaluation
.
Además, en este caso, creo que su código que enumera las instancias de Evaluation
que desea es lo correcto; no exija más de lo que realmente necesita.
Pero ciertamente hay casos en los que sería bueno poder cuantificar las restricciones de clase a lo largo de las líneas que describe, y no es posible directamente. Un ejemplo es que es posible que desee realizar de forma automática MonadPlus
casos de Monoid
(utilizando un tipo de envoltorio para evitar problemas OverlappingInstances
):
newtype MonoidWrapper m a = MonoidWrapper { unMonoidWrapper :: m a }
instance Monad m => Monad (MonoidWrapper m) where ...
instance (Monad m, forall a . Monoid (m a)) => MonadPlus (MonoidWrapper m) where
mzero = MonoidWrapper mempty
mplus (MonoidWrapper a) (MonoidWrapper b) = MonoidWrapper (mappend a b)
no se puede escribir esto, pero utilizando GADTs o tipos existenciales puede simular que, con un poco de dolor sintáctico:
data MonoidDict a where
MonoidDict :: Monoid a => MonoidDict a
class AlwaysMonoid m where
alwaysMonoidDict :: MonoidDict (m a) -- note the implicit forall a here
instance Monad m => Monad (MonoidWrapper m)
instance (Monad m, AlwaysMonoid m) => MonadPlus (MonoidWrapper m) where
mzero = mymzero
where
-- needed to give name to 'a' for ScopedTypeVariables
mymzero :: forall a . MonoidWrapper m a
mymzero = case (alwaysMonoidDict :: MonoidDict (m a)) of
MonoidDict -> MonoidWrapper mempty
mplus = mymplus
where
mymplus :: forall a . MonoidWrapper m a
-> MonoidWrapper m a -> MonoidWrapper m a
mymplus (MonoidWrapper a) (MonoidWrapper b)
= case (alwaysMonoidDict :: MonoidDict (m a)) of
MonoidDict -> MonoidWrapper (mappend a b)
Gracias, jugaré un poco con esto :) – raichoo