Wir haben einige hervorragende Antworten hatte, aber Als Täter dachte ich, ich würde weggehen einige Bemerkungen.
Ja, es gibt mehrere gleichwertige Darstellungen dieser Lemmas. Die Präsentation, die ich verwende, ist eine davon, und die Wahl ist größtenteils eine pragmatische. In diesen Tagen (in einer neueren Code-Basis), gehe ich so weit definieren
-- Holds :: Constraint -> *
type Holds c = forall t . (c => t) -> t
Dies ist ein Beispiel für einen Eliminator Typen: es abstrahiert über das, was es liefert (das Motiv der Beseitigung) und es erfordert, dass Sie null oder mehr Methoden (eine, hier) des Erreichens des Motivs unter spezifischeren Umständen zu konstruieren. Der Weg es zu lesen ist rückwärts. Es sagt
Wenn Sie ein Problem haben (bewohnen ein anderes Motiv Typ t
), und sonst niemand helfen kann, vielleicht können Sie Fortschritte machen, indem Zwang c
in Ihrer Methode angenommen.
Da die Sprache der Zwänge Verbindung (aka fache Vervielfachung) zugibt, wir die Mittel erwerben Lemmata des Formulars
lemma :: forall x1 .. xn. (p1[x1 .. xn],.. pm[x1 .. xn]) -- premises
=> t1[x1 .. xn] -> .. tl[x1 .. xn] -- targets
-> Holds (c1[x1 .. xn],.. ck[x1 .. xn]) -- conclusions
und es könnte sogar zu schreiben, dass einige Zwang, eine Prämisse p
oder ein c
Fassend hat die Form einer Gleichung
l[x1 .. xn] ~ r[x1 .. cn]
nun, wie die Bereitstellung eines lemma
, betrachten, das Problem der Füllung eines Lochs
_ :: Problem
verfeinern dieses _
durch die Eliminierung lemma
Angabe der Ziele . Das Motiv kommt von dem Problem zur Hand. Die Methode (Singular im Fall von Holds
) bleibt offen.
lemma target1 .. targetl $ _
und das Verfahren Loch wird nicht Typ geändert
_ :: Problem
aber GHC wird ein paar mehr Sachen kennen und somit eher Ihre Lösung zu glauben.
Manchmal gibt es eine Constraint-versus-Data-Auswahl, um festzulegen, was eine (Constraint-) Prämisse und was ein (Daten-) Ziel ist.Ich neige dazu, diese zu wählen, um Mehrdeutigkeiten zu vermeiden (Simon mag es zu schätzen x1 .. xn
, aber manchmal braucht einen Hinweis) und Beweis durch Induktion, die viel einfacher auf Ziele ist (oft die Singletons für Typ-Level-Daten) als auf Prämissen.
In Bezug auf die Bereitstellung für Gleichungen, können Sie sicher auf einen Datentyp Präsentation wechseln und eine Fallanalyse
case dataLemma target1 .. targetl of Refl -> method
ausbrechen und in der Tat, wenn Sie sich mit dem Dict
existentielle
ausstatten
data Dict (c :: Constraint) :: * where
Dict :: c => Dict c
Sie können ein Bündel auf einmal tun
case multiLemma blah blah blah of (Refl, Dict, Dict, Refl) -> method
aber Die Eliminatorform ist kompakter und lesbarer , wenn es höchstens eine Methode gibt. Tatsächlich können wir mehrere Lemmata Kette, ohne jemals nach rechts Schiebe
lemma1 .. $
...
lemmaj .. $
method
Wenn Sie eine solche Eliminator mit zwei oder mehr Fälle haben, ich glaube, es ist oft besser, es zu einpacken als GADT, so dass die Einsatzorte helfend jeder Tag Fall mit einer Konstruktorbezeichnung.
Wie auch immer, ja, der Punkt ist, die Präsentation der Fakten zu wählen, die uns am kompaktesten ermöglicht, die Reichweite der Constraint-Solving-Maschinerie von GHC zu erweitern, so dass mehr Sachen nur checket. Wenn Sie mit Simon in Verlegenheit geraten, ist es oft eine gute Strategie, sich Dimitrios von nebenan zu erklären.
Jemand zündet das @pigworker-Signal an. –
@ReinHenrichs Ich denke du musst ein 'Π' auf den Nachthimmel projizieren, um seine Aufmerksamkeit zu erregen. –
Während diese Frage aufgrund der Haskell-Beteiligung ein Thema ist, hat sie eine starke typentheoretische Tendenz, also könnte sie eine haben bessere Chance auf [cs.se] (oder vielleicht sogar [cstheory.se]). Nicht umbuchen; Sie können beantragen, dass Ihre Frage migriert wird, indem Sie sie markieren. – Gilles