Dies beantwortet Ihre Frage nicht genau, aber ein Ansatz, der manchmal funktioniert, ist, Ihre Interpretation Ihres Typs zu ändern. Zum Beispiel statt
%Vor%könnten Sie
verwenden %Vor%Auf diese Weise kann kein ungültiger Bereich dargestellt werden.
Diese Lösung verwendet abhängige Typen (und könnte zu schwergewichtig sein, überprüfen Sie, ob die Antwort von dfeuer für Ihre Bedürfnisse ausreicht).
Die Lösung verwendet das %code% -Modul von base sowie die typelits-Zeugen Paket.
Hier ist eine Differenzfunktion, die zwei ganzzahlige Argumente (statisch bekannt) annimmt und sich bei der Kompilierung beschwert, wenn die erste Zahl größer als die zweite ist:
%Vor%Wir können es von GHCi überprüfen:
%Vor%Aber was, wenn wir die Funktion mit zur Laufzeit bestimmten Werten verwenden wollen? Sprich, Werte, die wir aus der Konsole oder aus einer Datei lesen?
%Vor%In diesem Fall verwenden wir Funktionen wie %code% und %code% . Diese Funktionen können mit %code% fehlschlagen. Gelingt dies jedoch, geben sie einen Wert zurück, der eine Einschränkung "bezeugt". Und durch Mustervergleich auf dem Zeugen bringen wir diese Einschränkung in den Geltungsbereich (dies funktioniert, weil der Zeuge eine GADT ist).
In diesem Beispiel bringt die %code% -Musterübereinstimmung %code% für die beiden Argumente in den Gültigkeitsbereich. Und die %code% Musterübereinstimmung bringt die %code% Einschränkung in den Gültigkeitsbereich. Nur dann können wir unsere Funktion %code% aufrufen.
Also haben wir in gewisser Weise die ganze Arbeit verschoben, um sicherzustellen, dass die Argumente die erforderlichen Voraussetzungen aus der Funktion selbst erfüllen.
Ich stelle eine Funktion zur Verfügung, die zwei Parameter benötigt, eine ist eine Mindestgrenze und die andere ist eine Höchstgrenze. Wie kann ich mit Typen sicherstellen, dass beispielsweise die Mindestgrenze nicht größer ist als die Maximalgrenze?
Ich möchte es vermeiden, einen intelligenten Konstruktor zu erstellen und ein Maybe zurückzugeben, da dies die gesamte Verwendung umständlicher machen würde.
Danke
Was Sie verlangen, sind abhängige Typen. Es gibt ein nettes Tutorial dazu in Ссылка
Obwohl ich nicht weiß, wie freundlich es sein wird. Beachten Sie, dass die abhängige Typisierung in GHC 8.0 verbessert wurde, aber ich habe keine Erfahrung in diesem Bereich. Ich würde sicherstellen, dass Sie mit der Vorlage Haskell vertraut sind, wenn Sie nicht wollen, dass es umständlich ist.
Sie müssen den %code% -Typ nicht aufrufen, um "intelligente Konstruktoren" zu nutzen. Wenn Sie möchten, können Sie Konstruktoren der Form %code% oder %code% akzeptieren und trotzdem einen %code% type erzeugen, der richtig interpretiert, welcher welcher ist.
Zum Beispiel könnten Sie ein kleines Modul machen:
%Vor%Und jetzt, wenn Sie ein %code% mit %code% erstellen, wird das 2-Tupel automatisch so arrangiert, dass es in der Form %code% ist. Beachten Sie, dass der Konstruktor für %code% nicht exportiert wird. Daher kann der Benutzer des Moduls keine ungültige %code% erstellen. Sie müssen lediglich sicherstellen, dass Sie gültige Module in diesem Modul erstellen.