はのは、私は次のコードを記述しましょう:ハスケル - 解決する周期的なモジュールの依存関係
ゲームモジュール
module Game where
import Player
import Card
data Game = Game {p1 :: Player,
p2 :: Player,
isP1sTurn :: Bool
turnsLeft :: Int
}
プレーヤモジュール
module Player where
import Card
data Player = Player {score :: Int,
hand :: [Card],
deck :: [Card]
}
とカードモジュール
module Card where
data Card = Card {name :: String, scoreValue :: Int}
私はいくつかのタラを書くゲームが順不同になるまで、プレイヤーが自分の手札からカードを引いて、自分のスコアにボーナスを追加するロジックを実装する。
しかし、このコードが完成したら、私が書いたゲームモジュールは退屈です!
私はカードゲームをリファクタリングしたいので、単にスコアを追加するのではなく、カードが任意にゲームを変換します。
だから、私はもちろん、モジュール輸入がサイクルを形成します、次の
module Card where
import Game
data Card = Card {name :: String,
onPlayFunction :: (Game -> Game)
scoreValue :: Int}
にCard
モジュールを変更します。
この問題を解決するにはどうすればよいですか?
トリビアルソリューション:
すべてのファイルを同じモジュールに移動します。これは問題をうまく解決しますが、モジュール性は低下します。後で同じカードモジュールを別のゲームに再利用することはできません。
モジュール維持ソリューション:
がCard
に型パラメータを追加します。
module Card where
data Card a = {name :: String, onPlayFunc :: (a -> a), scoreValue :: Int}
がPlayer
に別のパラメータを追加します:Game
に1つの最後の修飾を有する
module Player where
data Player a {score :: Int, hand :: [card a], deck :: [card a]}
:
module Game where
data Game = Game {p1 :: Player Game,
p2 :: Player Game,
}
これはモジュール性を維持しますが、自分のデータ型にパラメータを追加する必要があります。データ構造が深く入れ子になっていれば、データに多くのパラメータを追加する必要がありました。この方法を複数のソリューションに使用する必要があった場合は、扱いにくいタイプの修飾子になる可能性があります。
このリファクタを解決するための他の有益な解決法がありますか、またはこれらの唯一の2つのオプションはありますか?
本当に必要な場合を除き、私はむしろ '{ - #SOURCE# - }'/.hs-bootメカニズムを避けることを強く推奨したいと思います。 – leftaroundabout
@leftroundabout:はい、私は気難しくて不快ですが、(imho)ではない[wiki](https://wiki.haskell.org/Mutually_recursive_modules)で言及されているものよりも何らかの議論があります小規模なプロジェクトにも適していますか? –