RankNTypes zum Beispiel Erklärungen?
-
08-10-2019 - |
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
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)