`updateWorld` of @Changaco can still be improved. I'll show it gradually so you can see what's going on. Firstly, we can eliminate duplication in `case` statement and use lens composition to eliminate second `over`: quantity Polymorph = quantityPolymorph quantity TeamPlayer = quantityTeamPlayer quantity LoneWolf = quantityLoneWolf updateWorld :: Fighter -> World -> World updateWorld fighter w = increment (quantity fighter) w where increment field = over (quantities . field) (+1) Then we can go pointfree. Pointfree is all about readability so don't do it whenever you feel readability is harmed. With coding experience more and more code will become readable for you. updateWorld = increment . quantity where increment field = over (quantities . field) (+1) Then we replace `over` with a more specialized version of it from `Control.Lens.Setter`: updateWorld = increment . quantity where increment field = (quantities . field) +~ 1 Now it seems beneficial to inline `increment`. I'll do in 2 steps. First, I make the actual parameter of `increment` explicit: updateWorld field = increment $ quantity field where increment field = (quantities . field) +~ 1 Then I inline: updateWorld :: Fighter -> World -> World updateWorld field = (quantities . quantity field) +~ 1 Another way to improve could be to use a `Map` or an `Array` for `QuantityHolder`: data World = World { _quantities :: M.Map Fighter Quantity } Below is full source using `Map`: {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} import Control.Lens import System.Random import qualified Data.Map as M import Data.Maybe newtype Quantity = Quantity Integer deriving (Eq,Num,Ord,Random,Show) data Fighter = TeamPlayer | LoneWolf | Polymorph deriving (Eq,Ord,Show) data World = World { _quantities :: M.Map Fighter Quantity } deriving (Show) $(makeLenses ''World) atFighter i = at i . iso fromJust Just updateWorld :: Fighter -> World -> World updateWorld field = (quantities . atFighter field) +~ 1 But it really depends on the usage scenarios you plan for `World`. Also note that lens interact with state monad transformer pretty well, so you may consider updateWorldS :: Fighter -> State World Quantity updateWorldS field = (quantities . atFighter field) <+= 1 Note that `World` is not passed in explicitly any more. And the type is more general than that, so you can combine state with IO and other monads should you wish: updateWorldS :: MonadState World m => Fighter -> m Quantity If you want to be able to report any extra value from `updateWorld` you can use the existing state monad: updateWorldS :: Fighter -> State World Bool updateWorldS field = (quantities . atFighter field) <+= 1 >> return errorBool where errorBool = False -- or True Or `MonadPlus` if you don't want to just report failure without extra info: updateWorldS field = (quantities . atFighter field) <+= 1 >> when errorBool mzero where errorBool = False Or `MonadError` if you want to supply an error value (of any type): updateWorldS4 field = (quantities . atFighter field) <+= 1 >> when errorBool (throwError "Game over")