【发布时间】:2016-08-27 00:03:06
【问题描述】:
假设我写了以下代码:
一个游戏模块
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}
然后我编写一些代码来实现玩家轮流从手中抽牌和打牌的逻辑,以增加他们的分数,直到游戏用完回合。
但是,写完这段代码后,我意识到我写的游戏模块很无聊!
我想重构纸牌游戏,这样当你玩纸牌时,不仅仅是添加分数,而是纸牌任意改变游戏。
所以,我将Card 模块更改为以下内容
module Card where
import Game
data Card = Card {name :: String,
onPlayFunction :: (Game -> Game)
scoreValue :: Int}
这当然使模块导入形成一个循环。
我该如何解决这个问题?
简单的解决方案:
将所有文件移动到同一个模块。这很好地解决了问题,但降低了模块化;我以后不能在另一个游戏中重复使用相同的卡片模块。
模块维护解决方案:
给Card添加类型参数:
module Card where
data Card a = {name :: String, onPlayFunc :: (a -> a), scoreValue :: Int}
给Player添加另一个参数:
module Player where
data Player a {score :: Int, hand :: [card a], deck :: [card a]}
最后修改Game:
module Game where
data Game = Game {p1 :: Player Game,
p2 :: Player Game,
}
这保持了模块化,但需要我为我的数据类型添加参数。如果数据结构嵌套得更深,我可能不得不在我的数据中添加大量参数,如果我不得不将这种方法用于多种解决方案,我最终可能会得到数量庞大的类型修饰符。
那么,有没有其他有用的解决方案来解决这个重构,还是只有这两个选项?
【问题讨论】: