    {-# LANGUAGE RankNTypes #-}
    module Control.Foldl.Optics where

    import Data.Profunctor
    import Control.Applicative

    type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)

    type Prism' s a = Prism s s a a

    prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
    prism bt seta = dimap seta (either pure (fmap bt)) . right'
    {-# INLINE prism #-}

    _Left :: Prism (Either a c) (Either b c) a b
    _Left = prism Left $ either Right (Left . Right)
    {-# INLINE _Left #-}

    _Right :: Prism (Either c a) (Either c b) a b
    _Right = prism Right $ either (Left . Left) Right
    {-# INLINE _Right #-}