How to do it...

  1. Create a new project working-with-lenses, with a simple stack template:
        stack new working-with-lenses simple
  1. Add a dependency on lens library in the build-depends sub-section of the executable section:
        executable working-with-lenses
         hs-source-dirs:      src
         main-is:             Main.hs
         default-language:    Haskell2010
         build-depends:       base >= 4.7 && < 5
                              , lens
  1. Open src/Main.hs. We will be adding our source here. Add a TemplateHaskell extension for creating lenses for the user-defined data types. Define the Main module, and import the necessary imports:
        {-# LANGUAGE TemplateHaskell #-}

        module Main where

        import Control.Lens.TH
        import Control.Lens
  1. Define a data type, Line, which is composed of two end Points. Note that we used *_* for naming the fields:
        data Point a = Point { _x :: a, _y :: a } deriving Show
        data Line a = Line { _start :: Point a, _end :: Point a }  
deriving Show
  1. Create lenses for Point and Line. We use TemplateHaskell support in lens to automatically create the lenses for Point and Line:
        makeLenses ''Point
        makeLenses ''Line

   This will remove the underscores from the field names, and make lenses out of        them.

  1. Use the data types, and lenses in the main function:
        main :: IO ()
        main = do
         let line = Line (Point 5 7) (Point 11 13)
         putStrLn $ "Line " ++ show line
         putStrLn $ "Using lenses"

         -- Get the x coordinates of the start point
         putStrLn "Start point of line"
         print $ view start line
         putStrLn "Composing lenses"
         putStrLn "X of end of the line"
         print $ view (end . x) line

         putStrLn "Using setters"
         putStrLn "Setting Y coordinate of end of the line"
-- Supply a function to modify the coordinate (const 17) print $ over (end . y) (const 17) line putStrLn "Making it fancier with ^." putStrLn "Access X of start of line" print $ line ^. (start . x)
  1. Build and execute the project:
        stack build
        stack exec -- working-with-lenses
  1.   You should see the following output: