- Create a new project working-with-prism with a simple stack template:
stack new working-with-prism simple
- 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
- 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
- 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
- Make the lens and prism out of it:
makeLenses ''Point makeLenses ''Shape makePrisms ''Shape
- 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
- 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
- Use the lenses and prisms in the main function:
main :: IO () main = usePrism
- Build and execute the project:
stack build stack exec -- working-with-prism
- You should see the following output:
