{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} -- | -- Module: Optics.VL -- -- This module provides compatibility layer for converting from/to van Laarhoven -- encoding of 'Iso's, 'Prism's, 'Lens'es, 'IxLens'es, 'AffineTraversal's, -- 'IxAffineTraversal's, 'Traversal's and 'IxTraversal's to their optics -- equivalents. module Optics.VL ( -- * Iso IsoVL , IsoVL' , isoVL , toIsoVL , withIsoVL -- * Prism , PrismVL , PrismVL' , prismVL , toPrismVL , withPrismVL -- * Lens , LensVL , LensVL' , lensVL , toLensVL , withLensVL -- * IxLens , IxLensVL , IxLensVL' , ilensVL , toIxLensVL , withIxLensVL -- * AffineTraversal , AffineTraversalVL , AffineTraversalVL' , atraversalVL , atraverseOf -- * IxAffineTraversal , IxAffineTraversalVL , IxAffineTraversalVL' , iatraversalVL , iatraverseOf -- * Traversal , TraversalVL , TraversalVL' , traversalVL , traverseOf -- * IxTraversal , IxTraversalVL , IxTraversalVL' , itraversalVL , itraverseOf ) where import Data.Coerce import Data.Functor.Identity import Data.Profunctor.Indexed ((.#), (#.)) import qualified Data.Profunctor as P import qualified Data.Profunctor.Indexed as IP import Optics.Internal.Optic import Optics.Core newtype WrappedIxProfunctor p i a b = WrapIxProfunctor { unwrapIxProfunctor :: p i a b } instance IP.Profunctor p => P.Profunctor (WrappedIxProfunctor p i) where dimap f g (WrapIxProfunctor piab) = WrapIxProfunctor (IP.dimap f g piab) lmap f (WrapIxProfunctor piab) = WrapIxProfunctor (IP.lmap f piab) rmap g (WrapIxProfunctor piab) = WrapIxProfunctor (IP.rmap g piab) {-# INLINE dimap #-} {-# INLINE lmap #-} {-# INLINE rmap #-} instance IP.Choice p => P.Choice (WrappedIxProfunctor p i) where left' (WrapIxProfunctor piab) = WrapIxProfunctor (IP.left' piab) right' (WrapIxProfunctor piab) = WrapIxProfunctor (IP.right' piab) {-# INLINE left' #-} {-# INLINE right' #-} ---------------------------------------- newtype WrappedProfunctor p f i a b = WrapProfunctor { unwrapProfunctor :: p a (f b) } instance (P.Profunctor p, Functor f) => IP.Profunctor (WrappedProfunctor p f) where dimap f g (WrapProfunctor pafb) = WrapProfunctor (P.dimap f (fmap g) pafb) lmap f (WrapProfunctor pafb) = WrapProfunctor (P.lmap f pafb) rmap g (WrapProfunctor pafb) = WrapProfunctor (P.rmap (fmap g) pafb) {-# INLINE dimap #-} {-# INLINE lmap #-} {-# INLINE rmap #-} lcoerce' = IP.lmap coerce rcoerce' = IP.rmap coerce {-# INLINE lcoerce' #-} {-# INLINE rcoerce' #-} instance (P.Choice p, Applicative f) => IP.Choice (WrappedProfunctor p f) where left' (WrapProfunctor pafb) = WrapProfunctor (P.rmap (either (fmap Left) (pure . Right)) (P.left' pafb)) right' (WrapProfunctor pafb) = WrapProfunctor (P.rmap (either (pure . Left) (fmap Right)) (P.right' pafb)) {-# INLINE left' #-} {-# INLINE right' #-} ---------------------------------------- -- | Type synonym for a type-modifying van Laarhoven iso. type IsoVL s t a b = forall p f. (P.Profunctor p, Functor f) => p a (f b) -> p s (f t) -- | Type synonym for a type-preserving van Laarhoven iso. type IsoVL' s a = IsoVL s s a a -- | Build an 'Iso' from the van Laarhoven representation. isoVL :: forall s t a b. IsoVL s t a b -> Iso s t a b isoVL f = Optic $ IP.rcoerce @(Identity t) @t . (unwrapIxProfunctor #. f .# WrapIxProfunctor) . IP.rcoerce @b @(Identity b) {-# INLINE isoVL #-} -- | Convert an 'Iso' to the van Laarhoven representation. toIsoVL :: Is k An_Iso => Optic k is s t a b -> IsoVL s t a b toIsoVL o = unwrapProfunctor #. getOptic (castOptic @An_Iso o) .# WrapProfunctor {-# INLINE toIsoVL #-} -- | Work with an 'Iso' in the van Laarhoven representation. withIsoVL :: Is k An_Iso => Optic k is s t a b -> (IsoVL s t a b -> r) -> r withIsoVL o k = k (toIsoVL o) {-# INLINE withIsoVL #-} ---------------------------------------- -- | Type synonym for a type-modifying van Laarhoven prism. type PrismVL s t a b = forall p f. (P.Choice p, Applicative f) => p a (f b) -> p s (f t) -- | Type synonym for a type-preserving van Laarhoven prism. type PrismVL' s a = PrismVL s s a a -- | Build a 'Prism' from the van Laarhoven representation. prismVL :: forall s t a b. PrismVL s t a b -> Prism s t a b prismVL f = Optic $ IP.rcoerce @(Identity t) @t . (unwrapIxProfunctor #. f .# WrapIxProfunctor) . IP.rcoerce @b @(Identity b) {-# INLINE prismVL #-} -- | Convert a 'Prism' to the van Laarhoven representation. toPrismVL :: Is k A_Prism => Optic k is s t a b -> PrismVL s t a b toPrismVL o = unwrapProfunctor #. getOptic (castOptic @A_Prism o) .# WrapProfunctor {-# INLINE toPrismVL #-} -- | Work with a 'Prism' in the van Laarhoven representation. withPrismVL :: Is k A_Prism => Optic k is s t a b -> (PrismVL s t a b -> r) -> r withPrismVL o k = k (toPrismVL o) {-# INLINE withPrismVL #-}