data Game = Game {
_players :: [Player]
}
data Player = Player {
_cards :: [Card]
}
data Card = Card {
_status :: CardStatus
}
data CardStatus = Face | Back
Then I makeLenses
on the above data types.
The game quit condition is that all the cards in a player's hand are Back. So in my Game StateT monad, I access all the CardStatus and test them. Since I am new to Lens I'm wondering what's the elegant way to write this. A little bit lost in the forest of Lens operators.
The module Control.Lens.Fold
has many combinators for testing targets of lenses/folds/traversals: has
(useful for checking that a prism matches), anyOf
, noneOf
, allOf
...
In your example (assuming we have also generated the prisms for CardStatus
) we could do something like:
endGame :: Game -> Bool
endGame = anyOf (players.folded) (allOf (cards.folded.status) (has _Back))
Also, to find which players have winning hands, we could use filtered
:
winners :: Fold Game Player
winners = players.folded.filtered (allOf (cards.folded.status) (has _Back))
These functions are analogous to typical list functions, but can be applied directly to folds, so they don't yank you out as much of the lensy world. For example, we could go on composing winners
with another Fold
.