split-morphism-0.1.0.0: src/Control/Lens/Wedge.hs
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TemplateHaskell #-}
module Control.Lens.Wedge where
import Control.Lens
import Data.Functor.Invariant.TH
{- | Composition of a `Control.Lens.SplitMono.SplitMono` and a `Control.Lens.SplitEpi.SplitEpi`, yielding an even weaker structure where neither
`reverseGet . get` and `get . reverseGet` is an identity but both are idempotent.
-}
data Wedge a b = Wedge
{ get :: a -> b
, reverseGet :: b -> a
}
$(deriveInvariant ''Wedge)
-- | Normalize `a` via a round-trip through `b`.
normalizeA :: Wedge a b -> a -> a
normalizeA w = reverseGet w . get w
-- | Normalize `b` via a round-trip through `a`.
normalizeB :: Wedge a b -> b -> b
normalizeB w = get w . reverseGet w
-- | Swapping `get` and `reverseGet` yields a Wedge.
reverse :: Wedge a b -> Wedge b a
reverse (Wedge f g) = Wedge g f
-- | Compose with another Wedge.
composeWedge :: Wedge a b -> Wedge b c -> Wedge a c
composeWedge (Wedge x y) (Wedge q w) =
Wedge (q . x) (y . w)
-- | Compose with an Iso.
composeIso :: Wedge a b -> Iso' b c -> Wedge a c
composeIso (Wedge x y) i =
Wedge ((^. i) . x) (y . review i)
-- | An Isomorphism is trivially a Wedge.
fromIso :: Iso' a b -> Wedge a b
fromIso i = Wedge (^. i) (review i)