-- | This module provides linear prisms.
--
-- A @Prism s t a b@ is equivalent to @(s \#-> Either a t, b \#-> t)@ for some
-- /sum type/ @s@. In the non-polymorphic version, this is a @(s \#-> Either a
-- s, a \#-> s)@ which represents taking one case of a sum type and a way to
-- build the sum-type given that one case. A prism is a traversal focusing on
-- one branch or case that a sum type could be.
--
-- = Example
--
-- @
-- {-# LANGUAGE LinearTypes #-}
-- {-# LANGUAGE LambdaCase #-}
-- {-# LANGUAGE FlexibleContexts #-}
-- {-# LANGUAGE NoImplicitPrelude #-}
-- {-# LANGUAGE GADTs #-}
--
-- import Control.Optics.Linear.Internal
-- import Prelude.Linear
-- import qualified Data.Functor.Linear as Data
--
-- -- We can use a prism to do operations on one branch of a sum-type
-- -- (This is a bit of a toy example since we could use @over@ for this.)
-- formatLicenceName :: PersonId %1-> PersonId
-- formatLicenceName personId =
--   Data.fmap modLisc (match pIdLiscPrism personId) & \case
--     Left personId' -> personId'
--     Right lisc -> build pIdLiscPrism lisc
--   where
--     modLisc :: Licence %1-> Licence
--     modLisc (Licence nm x) = Licence (nm ++ "\n") x
--
-- data PersonId where
--   IdLicence :: Licence %1-> PersonId
--   SSN :: Int %1-> PersonId
--   BirthCertif :: String %1-> PersonId
--   -- And there could be many more constructors ...
--
-- -- A Licence is a name and number
-- data Licence = Licence String Int
--
-- pIdLiscPrism :: Prism' PersonId Licence
-- pIdLiscPrism = prism IdLicence decompose where
--   decompose :: PersonId %1-> Either PersonId Licence
--   decompose (IdLicence l) = Right l
--   decompose x = Left x
-- @
--
module Control.Optics.Linear.Prism
  ( -- * Types
    Prism, Prism'
    -- * Composing optics
  , (.>)
    -- * Common optics
  , _Left, _Right
  , _Just, _Nothing
    -- * Using optics
  , match, build
  , withPrism
    -- * Constructing optics
  , prism
  )
  where

import Control.Optics.Linear.Internal