野球選手、チーム、コーチの統計を追跡するために、次のデータモデルがあるとします。
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)
ここで、通常はステーキ狂信者であるマネージャーがさらに多くのステーキを食べたいとしましょう。そのため、マネージャーの食事のステーキ含有量を増やすことができる必要があります。この関数の2つの可能な実装は次のとおりです。
1)これは多くのパターンマッチングを使用し、すべてのコンストラクターのすべての引数の順序を正しく取得する必要があります...2回。それはあまりうまくスケーリングしないか、非常に保守可能/読みやすいようです。
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
私の質問は、これらの1つが他よりも優れているのか、それともHaskellコミュニティ内でより好まれているのかということです。これを行うためのより良い方法はありますか(コンテキストを維持しながらデータ構造の奥深くで値を変更するため)?効率については心配していません。コードの優雅さ/一般性/保守性だけを気にしています。
Clojureにこの問題(または同様の問題?)があることに気づきました: -関数型プログラミングとHaskellおよび静的型付けのコンテキストでupdate-in
理解しようとしていると思います。update-in