I have a function that produces an updated board from an input and a board, if the move is permitted by the rules of the game:
move :: Input -> Board -> Maybe Board
The board is wrapped in the GameState
type with some additional data:
type GameState = (Board, ...)
Now I'd like to use lenses to update the board in the game state if move
yields Just
a value.
I can do this with a helper function:
updateGameState :: Input -> GameState -> GameState
updateGameState input gs = gs & _1 %~ (f $ move input)
where
f g x = maybe x id (g x)
However, I'm wondering if there is a combinator that modifies the target of a
Lens
only if the supplied function returns a Just
. I've found the ?~
operator, but that handles partiality on the left hand side.
Is there a (likely more general) combinator that can achieve this, or is there another way to express this in a terse and idiomatic way?
You could do
import Control.Applicative
import Data.Maybe
updateGameState :: Input -> GameState -> GameState
updateGameState input = fromMaybe <*> _1 (move input)
-- updateGameState x s = fromMaybe s $ _1 $ move x
This uses the fact that Lens s t a b
is a type alias for forall f . Functor f => (a -> f b) -> (s -> f t)
, so we can choose to use Maybe
as f
and get a function of type GameState -> Maybe GameState
.