I’m currently working on a Dominion simulator in Haskell which requires a few constantly changing records to accurately represent the game-play. While I first looked at using functions that returns updated records, I realized this would get complex as the records became more nested and the multiple functions per update complicated rather simple logic.

data Card = Card {
  name     = CardName,
  value    = CardValue, 
  cardType = CardType
}

data Deck = Deck {
  cards = [Card]
}

data Hand = Hand {
  cards = [Card]
}

drawCard    :: Deck -> Hand -> Hand
discardHand :: Hand -> Hand
discardCard :: Hand -> Hand
-- etc...

What I wanted to do is just update a records field in the ‘cleanest’ way possible with minimal line noise. That’s when I started looking at Lens, a Haskell library that lets you have CRUD-like access to deeply nested record types. After battling the usual Haskell jargon for an afternoon I got a few of the simpler lenses working and thought I’d store them here for the next time I need them.

The combinators in Control.Lens provide a highly generic toolbox for composing families of getters, folds, isomorphisms, traversals, setters and lenses and their indexed variants. - Huh?

First we declare our imports, language extensions, and create a new record type.

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Person = Person {
  _name = String,
  _age  = Int
}
makeLenses ''Person

There’s a little magic going on here. First we mark a record to be lens’d by adding makeLenses ''<recordName>. We then mark each field in that record to be lens’d by prepending them with underscores. After this we can get, set, and general update complex records in a much simpler way (albeit with some pretty interesting syntax choices).

-- View
person ^. name

-- Set
person $ name .~ "CSEdd"

-- Modify
person $ name %~ "Edd"

You can also use Lenses on other datatypes too. For example if you wanted to get the third character of “Lenses” you could write "Lenses" ^? ix 3. Told you the syntax was interesting right?

You can read more about Lens here or Edward Kmetts FAQ here.