Frage

Ich habe mit RankNTypes vor kurzem und Wunder herum spielen, wenn es möglich ist, sie zu benutzen in Beispiel Erklärungen.

Hier ist ein einfaches Beispiel mit Open-Datentypen

data (Expr a, Expr b) => Add a b = Add a b deriving(Show)                          

instance (Expr a, Expr b) => Expr (Add a b)

instance (Evaluation a, Evaluation b) => Evaluation (Add a b) where
  eval (Add x y) = eval x + eval y

Hier habe ich zu schreiben Einschränkungen wie (Auswertung eine, Bewertung b), aber im Grunde Ich möchte nur eine zu schreiben so etwas wie (forall a. Bewertung a). Ist das überhaupt möglich?

Viele Grüße, raichoo

War es hilfreich?

Lösung

(forall a . Evaluation a) nicht wirklich Sinn machen. 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, Ihr Code die Instanzen von Evaluation Auflistung, dass Sie das Richtige zu tun ist; nicht verlangen, mehr als Sie tatsächlich benötigen.

Aber es gibt sicherlich Fälle, in denen es schön wäre, der Lage sein, Einschränkungen zu quantifizieren über Klasse entlang der Linien, die Sie beschreiben, und es ist direkt nicht möglich. Ein Beispiel dafür ist, dass Sie vielleicht zu automatisch MonadPlus Instanzen von Monoid (mit einem Wrapper-Typ zu vermeiden OverlappingInstances Problemen) 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)

Sie können dies nicht schreiben, aber mit GADTs oder existentiellen Typen können Sie es simulieren, mit einigem syntaktischen Schmerz:

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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top