{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | This module provides linear lenses.
--
-- A @Lens s t a b@ is equivalent to a @(s %1-> (a,b %1-> t)@.  It is a way to
-- cut up an instance of a /product type/ @s@ into an @a@ and a way to take a
-- @b@ to fill the place of the @a@ in @s@ which yields a @t@. When @a=b@ and
-- @s=t@, this type is much more intuitive: @(s %1-> (a,a %1-> s))@.  This is a
-- traversal on exactly one @a@ in a @s@.
--
-- = Example
--
-- @
-- {-# LANGUAGE LinearTypes #-}
-- {-# LANGUAGE FlexibleContexts #-}
-- {-# LANGUAGE NoImplicitPrelude #-}
--
-- import Control.Optics.Linear.Internal
-- import Prelude.Linear
--
-- import Control.Optics.Linear.Internal
-- import Prelude.Linear
-- -- We can use a lens to, for instance, linearly modify a sub-piece in
-- -- a nested record
-- modPersonZip :: Person %1-> Person
-- modPersonZip = over (personLocL .> locZipL)  (\x -> x + 1)
--
-- -- A person has a name and location
-- data Person = Person String Location
--
-- -- A location is a zip code and address
-- data Location = Location Int String
--
-- personLocL :: Lens' Person Location
-- personLocL = lens (\(Person s l) -> (l, \l' -> Person s l'))
--
-- locZipL :: Lens' Location Int
-- locZipL = lens (\(Location i s) -> (i, \i' -> Location i' s))
-- @
module Control.Optics.Linear.Lens
  ( -- * Types
    Lens,
    Lens',

    -- * Composing lens
    (.>),

    -- * Common optics
    _1,
    _2,

    -- * Using optics
    get,
    set,
    gets,
    setSwap,
    over,
    overU,
    reifyLens,
    withLens,

    -- * Constructing optics
    lens,
  )
where

import Control.Optics.Linear.Internal