(forall a . Evaluation a)
nicht wirklich Sinn: es würde bedeuten, dass jede einzelne Art (einschließlich aller künftigen Typ könnte jemand machen) eine Instanz von Evaluation
war.
Auch in diesem Fall denke ich, dass Ihr Code die Instanzen von Evaluation
, die Sie wollen, ist das Richtige zu tun; fordere nicht mehr, als du wirklich brauchst.
Aber es gibt sicherlich Fälle, in denen es gut wäre, Klassenbeschränkungen entlang der von Ihnen beschriebenen Grenzen zu quantifizieren, und dies ist nicht direkt möglich. Ein Beispiel dafür ist, dass Sie automatisch wünschen konnten MonadPlus
Instanzen von Monoid
(mit einem Wrapper OverlappingInstances
Probleme zu vermeiden) machen:
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)
du nicht schreiben kann, aber unter Verwendung von GADTs oder existentielle Typen, die Sie simulieren können, mit ein paar syntaktischen Schmerzen:
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)
Danke, ich werde ein wenig damit spielen :) – raichoo