How to do it...

  1. Create a new project working-with-prism with a simple stack template:
        stack new working-with-prism simple
  1. Add a dependency on the lens library in the build-depends sub-section of the executable section:
     executable working-with-prism
      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. Enable TemplateHaskell, as we will produce Prism using the template Haskell. Add the Main module. Import the template haskell module for lens, alongwith other imports:
        {-# LANGUAGE TemplateHaskell #-}

        module Main where

        import Control.Lens
        import Control.Lens.TH
  1. Define the sum data type:
    data Point = Point { _x :: Double, _y :: Double } deriving Show
    data Shape = Rectangle { _leftTop :: Point, _rightBottom ::   
| Point } Circle { _centre :: Point, _radius :: Double } deriving Show
  1. Make the lens and prism out of it:
        makeLenses ''Point
        makeLenses ''Shape
        makePrisms ''Shape
  1. Create some shapes. Write two functions, one to create a rectangle of some size, and another to make a circle, with some radius value and a center:
        makeRectangle :: Shape
        makeRectangle = Rectangle (Point 0 0) (Point 100 100)

        makeCircle :: Shape
        makeCircle = Circle (Point 0 0) 25.0
  1. Work with Shape using prism and lenses
 usePrism :: IO ()
 usePrism = do
  let rect = makeRectangle
      circ = makeCircle
  putStrLn "Create two shapes"
  print rect
  print circ

  -- Check if we are dealing with rectangle
  putStrLn "Are we dealing with a rectangle"
  print $ rect ^? _Rectangle

  putStrLn "Get first point of rectangle"
  print $ rect ^? _Rectangle . _1

  putStrLn "Get Y coordinate of the right bottom point of  
rectangle"
print $ rect ^? _Rectangle . _2 . y putStrLn "Get the rectangle back from two points" print $ _Rectangle # (Point (-1) (-1), Point 1 1) putStrLn "Get radius of a circle" print $ circ ^? _Circle . _2 putStrLn "Create circle from center and point" print $ (Point 0 0, 10.0) ^. re _Circle putStrLn "Change radius of the circle (from 25 to 3)" print $ over (_Circle . _2) (const 3) circ putStrLn "Get details of rectangle back from rectangle by
traversing"
print $ rect ^.. _Rectangle -- This is equivalent to toListOf print $ toListOf _Rectangle rect -- Create list of shapes let shapes = [rect, circ] putStrLn "Return result if all are rectangles" print $ shapes ^.. below _Rectangle putStrLn "Now try with all rectangles" let rects = [rect, rect] print $ rects ^.. below _Rectangle
  1. Use the lenses and prisms in the main function:
        main :: IO ()
        main = usePrism
  1. Build and execute the project:
        stack build
        stack exec -- working-with-prism
  1. You should see the following output: