Sagen wir, ich den folgenden Code schreiben:Haskell - Lösung zyklischen Modulabhängigkeits
ein Spielmodul
module Game where
import Player
import Card
data Game = Game {p1 :: Player,
p2 :: Player,
isP1sTurn :: Bool
turnsLeft :: Int
}
ein Spieler Modul
module Player where
import Card
data Player = Player {score :: Int,
hand :: [Card],
deck :: [Card]
}
und ein Kartenmodul
module Card where
data Card = Card {name :: String, scoreValue :: Int}
Ich schreibe dann etwas Kabeljau e Logik zu implementieren, bei der die Spieler abwechselnd Karten aus ihrer Hand ziehen und spielen, um Boni zu ihren Punktzahlen hinzuzufügen, bis das Spiel aus den Zügen ausgeht.
Allerdings merke ich nach Abschluss dieses Codes, dass das Spielmodul, das ich geschrieben habe, langweilig ist!
Ich möchte das Kartenspiel umgestalten, also wenn Sie eine Karte spielen, anstatt nur eine Kerbe hinzuzufügen, stattdessen verwandelt die Karte willkürlich das Spiel.
So ändere ich den Card
Modul an folgende
module Card where
import Game
data Card = Card {name :: String,
onPlayFunction :: (Game -> Game)
scoreValue :: Int}
was natürlich die Modulimporte einen Zyklus macht bilden.
Wie behebe ich dieses Problem?
Trivial Lösung:
Verschieben Sie alle Dateien auf dem gleichen Modul. Dies löst das Problem gut, reduziert aber die Modularität; Ich kann das gleiche Kartenmodul später nicht für ein anderes Spiel wiederverwenden.
Modul Aufrechterhaltung Lösung:
hinzufügen Typ Parameter Card
:
module Card where
data Card a = {name :: String, onPlayFunc :: (a -> a), scoreValue :: Int}
einen anderen Parameter In den Player
:
module Player where
data Player a {score :: Int, hand :: [card a], deck :: [card a]}
Mit einem letzten Änderung Game
:
module Game where
data Game = Game {p1 :: Player Game,
p2 :: Player Game,
}
Das hält die Modularität, aber ich muss meine Datentypen Parameter hinzufügen. Wenn die Datenstrukturen tiefer verschachtelt wären, könnte ich meinen Daten viele Parameter hinzufügen müssen, und wenn ich diese Methode für mehrere Lösungen verwenden müsste, könnte ich mit einer unhandlichen Anzahl von Typmodifikatoren enden.
Gibt es also andere nützliche Lösungen zur Lösung dieses Refactors, oder sind dies die einzigen zwei Optionen?
Ich würde eher empfehlen, die '{- # SOURCE # -}'/.hs-Boot-Mechanismus zu vermeiden, es sei denn, es ist wirklich notwendig. – leftaroundabout
@leftroundabout: Ja, ich finde es fummelig und unbehaglich, aber gibt es irgendwelche Argumente dagegen anders als die im [Wiki] genannten (https://wiki.haskell.org/Mutually_recursive_modules), die (imho) nicht sind so relevant für kleine Projekte? –