2010-10-23 6 views
6

Ich schreibe ein Schlangenspiel in Haskell. Dies sind einige der Dinge, die ich habe:Wie klein soll ich in Haskell Module machen?

  • A Coord Datentyp
  • A Line Datentyp
  • A Rect Datentyp
  • A Polygon Typ-Klasse, die mir erlaubt, eine Rect als ein zu erhalten Reihe von Linien ([Line]).
  • Eine Impassable Typ-Klasse, die ich ein Line als eine Reihe von Koordinaten erhalten kann ([Coord]), so dass ich Kollisionen zwischen anderen Impassable s erkennen kann.
  • Eine Draw Typklasse für alles, was ich auf den Bildschirm zeichnen möchte (HSCurses).
  • Schließlich verwende ich QuickCheck, also möchte ich Arbitrary Instanzen für viele dieser Dinge erklären.

Derzeit habe ich viele davon in separaten Modulen, so dass ich viele kleine Module habe. Ich habe bemerkt, dass ich eine Menge von ihnen füreinander importieren muss, also frage ich mich, was der Punkt war.

Ich bin besonders verwirrt über Arbitrary Instanzen. Bei der Verwendung von -Wall bekomme ich Warnungen über verwaiste Instanzen, wenn ich aber diese Instanzen zusammen in einer Testdatei, ich verstehe, dass ich diese Warnung vermeiden kann, indem ich diese Instanzen in das gleiche Modul wie wo der Datentyp definiert ist, aber dann brauche ich zu import Test.QuickCheck für alle diese Module, die albern erscheint, weil QuickCheck nur benötigt werden sollte, wenn Sie die Test-ausführbare Datei erstellen.

Jeder Hinweis auf das spezifische Problem mit QuickCheck wäre wünschenswert, ebenso wie die Anleitung zum allgemeineren Problem, wie Programme in Module unterteilt werden sollten.

Antwort

1

Im Allgemeinen habe ich mehr Wert auf die Modulschnittstelle gelegt, wie sie durch die Funktionen definiert ist, die sie offenlegt, und nicht auf die Datentypen, die sie zur Verfügung stellt. Haben einige Ihrer Typen einen gemeinsamen Satz von Funktionen? Dann würde ich sie in dasselbe Modul stecken.

Aber meine Praxis ist wahrscheinlich nicht die beste, da ich normalerweise kleine Programme schreibe. Ich würde empfehlen, einen Code von Hackage zu betrachten, um zu sehen, was Paketbetreuer tun.

Wenn es eine Möglichkeit gäbe, Pakete nach Community-Rating oder Anzahl der Downloads zu sortieren, wäre das ein guter Anfang. (Ich dachte es gäbe es, aber jetzt, wo ich es suche, kann ich es nicht finden.) Wenn das nicht klappt, schau dir Pakete an, die du bereits benutzt hast.

+0

Es gibt Links für Rankings nach Anzahl der Downloads und Anzahl der umgekehrten Abhängigkeiten hier: http://stackoverflow.com/questions/3663550/which-haskell-package-for-json/3663601#3663601 –

4

Sie können Ihren Kuchen haben und es auch essen. Sie können Module erneut exportieren.

Normalerweise verwende ich ein Modul, wenn ich eine vollständige Abstraktion habe - d. H. Wenn sich die Bedeutung eines Datentyps von seiner Implementierung unterscheidet. Da ich nur wenig über Ihren Code weiß, würde ich wahrscheinlich die Gruppen Polygon und Impassable zusammen gruppieren und vielleicht einen Collision Datentyp angeben, um darzustellen, was sie zurückgeben. Aber Coord, Line und Rect scheinen wie gute Abstraktionen und sie verdienen wahrscheinlich ihre eigenen Module.

+0

Alle Vorschläge, was zu tun ist über das QuickCheck-Problem? –

+1

Das ist ein schwieriges Problem, an dem ich gerade gearbeitet habe. Ich denke, Ihre beste Option ist gerade, sich mit den Waisen zu befassen, wie John es vorschlägt. Ich denke, der richtige Weg ist, Verteilerkombinatoren zu haben, also haben Sie statt "Instanz Arbitrary Coord" eine Funktion 'arbitraryCoord :: Distribution Coord'. In Tests ist es etwas umständlicher, aber es ist flexibler und modularer, da Sie mehrere Distributionen für denselben Typ haben können (insbesondere wenn zwei verschiedene Distributionen definiert sind, explodiert die Welt nicht). – luqui

2

Zu Testzwecken verwende ich separate Module für die Instanzen Arbitrary. Obwohl ich im Allgemeinen verwaiste Instanzen vermeide, werden diese Module nur beim Erstellen der Test-Executable erstellt, so dass ich nichts gegen die Waisen habe oder dass es nicht -Wall sauber ist. Sie können auch -fno-warn-orphans verwenden, um nur diese Warnmeldung zu deaktivieren.

+0

Sie haben ein separates Modul für _all_ die 'Arbitrary'-Instanzen? –

+0

@Ollie Saunders - es hängt von der Größe des Projekts ab. Für kleinere Projekte verwende ich zwei Module zum Testen: eines hat willkürliche Instanzen und anderen zusätzlichen Code, wenn nötig, und das andere Modul hat die QuickCheck-Eigenschaften. Bei größeren Projekten mag ich das Layout, das im Snap-Framework verwendet wird. Sie haben ein Testmodul für jedes reguläre Modul, das Arbitrary-Instanzen und Eigenschaftstests enthält. –

0

Eine Lösung mit QuickCheck besteht darin, den C-Präprozessor zu verwenden, um die arbiträren Instanzen beim Testen selektiv zu aktivieren. Sie fügen die Arbitrary-Instanzen direkt in Ihre Hauptmodule ein, umschließen sie jedoch mit Präprozessor-Makros und setzen dann ein "Test" -Flag in Ihre Cabal-Datei.

Verwandte Themen