假设我有以下数据模型,用于跟踪棒球运动员、球队和教练的统计数据:
data BBTeam = BBTeam { teamname :: String,
manager :: Coach,
players :: [BBPlayer] }
deriving (Show)
data Coach = Coach { coachname :: String,
favcussword :: String,
diet :: Diet }
deriving (Show)
data Diet = Diet { dietname :: String,
steaks :: Integer,
eggs :: Integer }
deriving (Show)
data BBPlayer = BBPlayer { playername :: String,
hits :: Integer,
era :: Double }
deriving (Show)
现在假设通常是牛排狂热者的经理想要吃更多的牛排——所以我们需要能够增加经理饮食中的牛排含量。以下是此功能的两种可能实现:
1)这使用了大量的模式匹配,我必须让所有构造函数的所有参数排序正确......两次。它似乎不能很好地扩展或非常易于维护/可读。
addManagerSteak :: BBTeam -> BBTeam
addManagerSteak (BBTeam tname (Coach cname cuss (Diet dname oldsteaks oldeggs)) players) = BBTeam tname newcoach players
where
newcoach = Coach cname cuss (Diet dname (oldsteaks + 1) oldeggs)
2) 这使用了 Haskell 记录语法提供的所有访问器,但我认为它也丑陋且重复,并且难以维护和阅读。
addManStk :: BBTeam -> BBTeam
addManStk team = newteam
where
newteam = BBTeam (teamname team) newmanager (players team)
newmanager = Coach (coachname oldcoach) (favcussword oldcoach) newdiet
oldcoach = manager team
newdiet = Diet (dietname olddiet) (oldsteaks + 1) (eggs olddiet)
olddiet = diet oldcoach
oldsteaks = steaks olddiet
我的问题是,其中一个比另一个更好,还是在 Haskell 社区中更受欢迎?有没有更好的方法来做到这一点(在保持上下文的同时修改数据结构深处的值)?我不担心效率,只担心代码优雅/通用性/可维护性。
我注意到在 Clojure 中存在这个问题(或类似问题?): update-in
- 所以我认为我试图update-in
在函数式编程和 Haskell 和静态类型的上下文中理解。