Created
June 7, 2014 10:53
-
-
Save ekmett/c5d58098fb7cee6ad306 to your computer and use it in GitHub Desktop.
towards generalized profunctor lenses
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE RankNTypes #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE FunctionalDependencies #-} | |
{-# LANGUAGE UndecidableInstances #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE DeriveDataTypeable #-} | |
{-# LANGUAGE PolyKinds #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE GADTs #-} | |
import qualified Control.Arrow as Arrow | |
import Control.Applicative | |
import Control.Category | |
import Data.Bitraversable | |
import Data.Functor.Identity | |
import Data.Monoid hiding (Product, Sum) | |
import Data.Traversable | |
import Data.Type.Equality | |
import Data.Typeable | |
import Data.Void | |
import Prelude hiding (map, id, (.), fst, snd) | |
import qualified Prelude | |
-- * Profunctors | |
-- p : C^op x D -> Set | |
class (Category c, Category d) => Profunctor (p :: x -> y -> *) c d | p -> c d where | |
dimap :: c a a' -> d b b' -> p a' b -> p a b' | |
lmap :: c a a' -> p a' b -> p a b | |
lmap f = dimap f id | |
rmap :: d b b' -> p a b -> p a b' | |
rmap = dimap id | |
type Iso c d s t a b = forall p. Profunctor p c d => p a b -> p s t | |
-- * Viewing | |
newtype Forget c r a b = Forget { runForget :: c a r } | |
instance Category k => Profunctor (Forget k r) k k where | |
dimap f g (Forget ar) = Forget (ar . f) | |
_Forget :: Iso (->) (->) (Forget c r a b) (Forget c' r' a' b') (c a r) (c' a' r') | |
_Forget = dimap runForget Forget | |
view :: Category k => (Forget k a a a -> Forget k a s s) -> k s a | |
view l = runForget $ l (Forget id) | |
newtype From p a b s t = From { runFrom :: p t s -> p b a } | |
_From :: Iso (->) (->) (From p a b s t) (From p' a' b' s' t') (p t s -> p b a) (p' t' s' -> p' b' a') | |
_From = dimap runFrom From | |
instance Profunctor p d c => Profunctor (From p a b) c d where | |
dimap f g = _From $ lmap (dimap g f) | |
from :: (From p a b a b -> From p a b s t) -> p t s -> p b a | |
from l = runFrom $ l (From id) | |
newtype Tagged k a b = Tagged { runTagged :: k (Terminal k) b } | |
instance Category k => Profunctor (Tagged k) k k where | |
dimap _ g (Tagged h) = Tagged (g.h) | |
instance Category k => Bifunctor (Tagged k) k k (->) where | |
bimap _ g (Tagged h) = Tagged (g.h) | |
coerce1 :: (Cartesian k, Profunctor p k k, Bifunctor p k k (->)) => p a e -> p b e | |
coerce1 = lmap terminal . first terminal | |
-- review :: (Tagged k b b -> Tagged k t t) -> k b t | |
-- review l = l (Tagged | |
-- k () b -> | |
-- * Natural transformations | |
-- newtype NAT (d :: y -> y -> *) (f :: x -> y) (g :: x -> y) = Nat { runNat :: forall a. d (f a) (g a) } | |
newtype Nat x y = Nat { runNat :: forall i. x i -> y i } | |
instance Category Nat where | |
id = Nat id | |
Nat f . Nat g = Nat (f . g) | |
instance Profunctor Nat Nat Nat where | |
dimap (Nat f) (Nat g) (Nat h) = Nat (dimap f g h) | |
-- * Lifting bifunctors | |
newtype Lift p f g a = Lift { lower :: p (f a) (g a) } -- could be used with Lift (,), Lift Either, Lift (->) to get corresponding entries for Nat | |
_Lift :: Iso (->) (->) (Lift p f g a) (Lift p' f' g' a') (p (f a) (g a)) (p' (f' a') (g' a')) | |
_Lift = dimap lower Lift | |
data (*) f g a = Product (f a) (g a) deriving (Eq,Ord,Show,Read,Typeable) | |
data (+) f g a = L (f a) | R (g a) deriving (Eq,Ord,Show,Read,Typeable) | |
data Pow f g a = Pow { runPow :: f a -> g a } deriving Typeable | |
_Pow :: Iso (->) (->) (Pow f g a) (Pow f' g' a') (f a -> g a) (f' a' -> g' a') | |
_Pow = dimap runPow Pow | |
data One a = One deriving (Eq,Ord,Show,Read,Typeable) | |
newtype K b a = K b deriving (Eq,Ord,Show,Read,Typeable) | |
newtype An f a = An (f a) deriving (Eq,Ord,Show,Read,Typeable) | |
data Zero a deriving Typeable | |
instance Show (Zero a) where showsPrec _ x = seq x undefined | |
instance Eq (Zero a) where a == b = seq a $ seq b True | |
instance Ord (Zero a) where compare a b = seq a $ seq b EQ | |
data Procompose (p :: x -> y -> *) (q :: y -> z -> *) (d :: x) (c :: z) where | |
Procompose :: p d a -> q a c -> Procompose p q d c | |
instance (Profunctor p c d, Profunctor q d e) => Profunctor (Procompose p q) c e where | |
dimap f g (Procompose p q) = Procompose (lmap f p) (rmap g q) | |
newtype Up (c :: x -> x -> *) (f :: y -> x) (a :: x) (b :: y) = Up { runUp :: c a (f b) } | |
newtype Down (d :: y -> y -> *) (f :: x -> y) (a :: x) (b :: y) = Down { runDown :: d (f a) b } | |
class (Category c, Category d) => Functorial f c d | f c -> d, f d -> c where | |
map :: c a b -> d (f a) (f b) | |
instance Functor g => Functorial g (->) (->) where | |
map = fmap | |
instance Functorial f d c => Profunctor (Up c f) c d where | |
dimap f g (Up h) = Up $ map g . h . f | |
instance Functorial f c d => Profunctor (Down d f) c d where | |
dimap f g (Down h) = Down $ g . h . map f | |
instance Profunctor (->) (->) (->) where | |
dimap f g h = g . h . f | |
class (Category c, Category d, Category e) => Bifunctor (p :: x -> y -> z) (c :: x -> x -> *) (d :: y -> y -> *) (e :: z -> z -> *) | p -> c d e where | |
bimap :: c a a' -> d b b' -> e (p a b) (p a' b') | |
first :: c a a' -> e (p a b) (p a' b) | |
first f = bimap f id | |
second :: d b b' -> e (p a b) (p a b') | |
second = bimap id | |
instance Bifunctor (,) (->) (->) (->) where | |
bimap = (Arrow.***) | |
first = Arrow.first | |
second = Arrow.second | |
instance Bifunctor Either (->) (->) (->) where | |
bimap = (Arrow.+++) | |
first = Arrow.left | |
second = Arrow.right | |
instance Bifunctor (*) Nat Nat Nat where | |
bimap (Nat f) (Nat g) = Nat $ \(Product as bs) -> Product (f as) (g bs) | |
first (Nat f) = Nat $ \(Product as bs) -> Product (f as) bs | |
second (Nat g) = Nat $ \(Product as bs) -> Product as (g bs) | |
instance Bifunctor (+) Nat Nat Nat where | |
bimap (Nat f) (Nat g) = Nat $ \ xs -> case xs of | |
L a -> L (f a) | |
R b -> R (g b) | |
class Bifunctor p k k k => Monoidal (p :: x -> x -> x) (k :: x -> x -> *) | p -> k where | |
type Id p k :: x | |
associate :: Iso k k (p (p a b) c) (p (p a' b') c') (p a (p b c)) (p a' (p b' c')) | |
lambda :: Iso k k (p (Id p k) a) (p (Id p k) a') a a' | |
rho :: Iso k k (p a (Id p k)) (p a' (Id p k)) a a' | |
instance Monoidal (,) (->) where | |
type Id (,) (->) = () | |
associate = dimap (\((a,b),c) -> (a,(b,c))) (\(a,(b,c)) -> ((a,b),c)) | |
lambda = dimap (\((),a) -> a) ((,)()) | |
rho = dimap (\(a,()) -> a) (\a -> (a,())) | |
instance Monoidal (*) Nat where | |
type Id (*) Nat = One | |
associate = dimap hither yon where | |
hither = Nat $ \(Product (Product as bs) cs) -> Product as (Product bs cs) | |
yon = Nat $ \(Product as (Product bs cs)) -> Product (Product as bs) cs | |
lambda = dimap hither yon where | |
hither = Nat $ \(Product One as) -> as | |
yon = Nat $ \as -> Product One as | |
rho = dimap hither yon where | |
hither = Nat $ \(Product as One) -> as | |
yon = Nat (\as -> Product as One) | |
instance Monoidal Either (->) where | |
type Id Either (->) = Void | |
associate = dimap hither yon where | |
hither (Left (Left a)) = Left a | |
hither (Left (Right b)) = Right (Left b) | |
hither (Right c) = Right (Right c) | |
yon (Left a) = Left (Left a) | |
yon (Right (Left b)) = Left (Right b) | |
yon (Right (Right c)) = Right c | |
lambda = dimap (\(Right a) -> a) Right | |
rho = dimap (\(Left a) -> a) Left | |
instance Monoidal (+) Nat where | |
type Id (+) Nat = Zero | |
associate = dimap hither yon where | |
hither = Nat $ \xs -> case xs of | |
L (L a) -> L a | |
L (R b) -> R (L b) | |
R c -> R (R c) | |
yon = Nat $ \xs -> case xs of | |
L a -> L (L a) | |
R (L b) -> L (R b) | |
R (R c) -> R c | |
lambda = dimap (Nat $ \(R a) -> a) (Nat R) | |
rho = dimap (Nat $ \(L a) -> a) (Nat L) | |
class Monoidal p k => Symmetric (p :: x -> x -> x) (k :: x -> x -> *) | p -> k where | |
swap :: k (p a b) (p b a) | |
default swap :: (Cartesian k, p ~ Product k) => k (p a b) (p b a) | |
swap = snd &&& fst | |
instance Symmetric (,) (->) where | |
swap (x,y) = (y,x) | |
instance Symmetric Either (->) where | |
swap = either Right Left | |
instance Symmetric (*) Nat where | |
swap = Nat $ \ (Product as bs) -> Product bs as | |
instance Symmetric (+) Nat where | |
swap = Nat $ \ xs -> case xs of | |
L a -> R a | |
R a -> L a | |
type Terminal k = Id (Product k) k | |
class Symmetric (Product k) k => Cartesian (k :: i -> i -> *) where | |
type Product k :: i -> i -> i | |
fst :: k (Product k x y) x | |
snd :: k (Product k x y) y | |
(&&&) :: k x y -> k x z -> k x (Product k y z) | |
terminal :: k x (Terminal k) | |
instance Cartesian (->) where | |
type Product (->) = (,) | |
fst = Prelude.fst | |
snd = Prelude.snd | |
(&&&) = (Arrow.&&&) | |
terminal = const () | |
instance Cartesian Nat where | |
type Product Nat = (*) | |
fst = Nat $ \(Product as _) -> as | |
snd = Nat $ \(Product _ bs) -> bs | |
Nat f &&& Nat g = Nat $ \as -> Product (f as) (g as) | |
terminal = Nat (const One) | |
class (Profunctor p k k, Cartesian k) => Strong p k | p -> k where | |
{-# MINIMAL first' | second' #-} | |
first' :: p a b -> p (Product k a x) (Product k b x) | |
first' = dimap swap swap . second' | |
second' :: p a b -> p (Product k x a) (Product k x b) | |
second' = dimap swap swap . first' | |
instance Strong (->) (->) where | |
first' = first | |
second' = second | |
instance Strong Nat Nat where | |
first' = first | |
second' = second | |
type Lens k s t a b = forall p. Strong p k => p a b -> p s t | |
type Initial k = Id (Sum k) k | |
class Symmetric (Sum k) k => Cocartesian (k :: i -> i -> *) where | |
type Sum k :: i -> i -> i | |
inl :: k x (Sum k x y) | |
inr :: k y (Sum k x y) | |
(|||) :: k x z -> k y z -> k (Sum k x y) z | |
initial :: k (Initial k) x | |
instance Cocartesian (->) where | |
type Sum (->) = Either | |
inl = Left | |
inr = Right | |
(|||) = either | |
initial = absurd | |
instance Cocartesian Nat where | |
type Sum Nat = (+) | |
inl = Nat L | |
inr = Nat R | |
Nat f ||| Nat g = Nat $ \xs -> case xs of | |
L a -> f a | |
R b -> g b | |
initial = Nat $ \ xs -> xs `seq` undefined | |
class (Profunctor p k k, Cocartesian k) => Choice p k | p -> k where | |
left' :: p a b -> p (Sum k a x) (Sum k b x) | |
right' :: p a b -> p (Sum k x a) (Sum k x b) | |
instance Choice (->) (->) where | |
left' = Arrow.left | |
right' = Arrow.right | |
instance Choice Nat Nat where | |
left' (Nat f) = Nat $ \xs -> case xs of | |
L a -> L (f a) | |
R b -> R b | |
right' (Nat g) = Nat $ \xs -> case xs of | |
L a -> L a | |
R b -> R (g b) | |
type Prism k s t a b = forall p. Choice p k => p a b -> p s t | |
class Cartesian k => CCC (k :: x -> x -> *) where | |
type Exp k :: x -> x -> x | |
apply :: Product k (Exp k a b) a `k` b | |
curried :: Iso (->) (->) (Product k a b `k` c) (Product k a' b' `k` c') (a `k` Exp k b c) (a' `k` Exp k b' c') | |
instance CCC (->) where | |
type Exp (->) = (->) | |
apply (f,x) = f x | |
curried = dimap curry uncurry | |
instance CCC Nat where | |
type Exp Nat = Pow | |
apply = Nat $ \(Product (Pow f) x) -> f x | |
curried = dimap hither yon where | |
hither (Nat f) = Nat $ \a -> Pow $ \b -> f (Product a b) | |
yon (Nat f) = Nat $ \(Product a b) -> case f a of Pow g -> g b | |
class (Functorial (Rep p) d c, Profunctor p c d) => Representable (p :: x -> y -> *) (c :: x -> x -> *) (d :: y -> y -> *) | p -> c d where | |
type Rep p :: y -> x | |
rep :: Iso (->) (->) (p a b) (p a' b') (c a (Rep p b)) (c a' (Rep p b')) | |
instance Representable (->) (->) (->) where | |
type Rep (->) = Identity | |
rep = dimap (Identity.) (runIdentity.) | |
instance Functorial f d c => Representable (Up c f) c d where | |
type Rep (Up c f) = f | |
rep = dimap runUp Up | |
class (Functorial (Corep p) c d, Profunctor p c d) => Corepresentable (p :: x -> y -> *) (c :: x -> x -> *) (d :: y -> y -> *) | p -> c d where | |
type Corep p :: x -> y | |
corep :: Iso (->) (->) (p a b) (p a' b') (d (Corep p a) b) (d (Corep p a') b') | |
instance Corepresentable (->) (->) (->) where | |
type Corep (->) = Identity | |
corep = dimap (.runIdentity) (.Identity) | |
instance Functorial f c d => Corepresentable (Down d f) c d where | |
type Corep (Down d f) = f | |
corep = dimap runDown Down | |
-- Well reasoned code ends. Below here are old ramblings from how I got here. | |
data (||) :: * -> * -> Bool -> * where | |
Fst :: a -> (a || b) False | |
Snd :: b -> (a || b) True | |
class Profunctor p k k => Walkable p k | p -> k where | |
pureP :: p a a | |
apP :: p a b -> p a c -> p a (Product k b c) | |
instance Walkable (->) (->) where | |
pureP = id | |
apP = (Arrow.&&&) | |
class Category k => Natural (k :: x -> x -> *) (f :: x -> y -> *) | k -> f where | |
natural :: k a b -> Nat (f a) (f b) | |
instance Natural (->) (K :: * -> () -> *) where | |
natural f = Nat $ \(K a) -> K (f a) | |
instance Natural Nat An where | |
natural (Nat f) = Nat $ \(An a) -> An (f a) | |
-- class Functorial (Mu k) (Nat k) k => Fixed k where -- requires a category of natual transformations over our base category. harder to express in haskell | |
class Fixed (k :: x -> x -> *) where | |
type Mu k :: (x -> x) -> x | |
type Nu k :: (x -> x) -> x | |
cata :: Functorial f k k => k (f a) a -> k (Mu k f) a | |
-- cata f = f . map (cata f) . view mu | |
ana :: Functorial f k k => k a (f a) -> k a (Nu k f) | |
-- ana g = view nu . map (ana g) . g | |
mu :: Iso k k (f (Mu k f)) (g (Mu k g)) (Mu k f) (Mu k g) | |
nu :: Iso k k (f (Nu k f)) (g (Nu k g)) (Nu k f) (Nu k g) | |
instance Cartesian k => Strong (Forget k r) k where | |
first' (Forget ar) = Forget (ar . fst) | |
newtype Fix f = In { out :: f (Fix f) } | |
instance Fixed (->) where | |
type Mu (->) = Fix | |
type Nu (->) = Fix | |
cata f = f . map (cata f) . out | |
ana g = In . map (ana g) . g | |
mu = dimap In out | |
nu = dimap In out | |
newtype FixF f a = InF { outF :: f (FixF f) a } | |
instance Fixed Nat where | |
type Mu Nat = FixF | |
type Nu Nat = FixF | |
cata f = f . map (cata f) . Nat outF | |
ana g = Nat InF . map (ana g) . g | |
mu = dimap (Nat InF) (Nat outF) | |
nu = dimap (Nat InF) (Nat outF) | |
-- type Traversal s t a b = | |
-- bi :: Bitraversable p => Traversal Nat (An (p a c)) (An (p a d)) (a || b) (c || d) | |
-- bi = undefined | |
-- type LensLike p k s t a b = | |
-- poly :: Functor f => ( (Un a) ~> Un b) -> Un s u -> f (Un t u)) -> LensLike f s t a b | |
-- poly l f s = runUn <$> l (\(Un a) -> Un <$> f a) (Un s) | |
{- | |
-- bilenses | |
type Bilens s t a b c d = forall f. Functor f => (a -> f b) -> (c -> f d) -> s -> f t | |
type Bitraversal s t a b c d = forall f. Applicative f => (a -> f b) -> (c -> f d) -> s -> f t | |
type Bifold s a c = forall f. (Applicative f, Contravariant f) => (a -> f a) -> (c -> f c) -> s -> f s | |
type Bigetter s a c = forall f. (Applicative f, Contravariant f) => (a -> f a) -> (c -> f c) -> s -> f s | |
type Biprism s t a b c d = forall p f. (Choice p, Applicative f) => p a (f b) -> p c (f d) -> p s (f t) | |
type Bisetter s t a b c d = forall p f. Settable f => (a -> f b) -> (c -> f d) -> s -> (f t) | |
type IndexedBitraversal i j s t a b c d = forall p q f. (Indexable i p, Indexable j q, Applicative f) => p a (f b) -> q c (f d) -> s -> f t | |
type IndexedBifold i j s a c = forall p q f. (Indexable i p, Indexable j q, Applicative f, Contravariant f) => p a (f a) -> q c (f c) -> s -> f s | |
type IndexedBigetter i j s a c = forall p q f. (Indexable i p, Indexable j q, Applicative f, Contravariant f) => p a (f a) -> q c (f c) -> s -> f s | |
type IndexedBisetter i j s a c = forall p q f. (Indexable i p, Indexable j q, Settable f) => p a (f a) -> q c (f c) -> s -> f s | |
type Bioptic p q r f s t a b c d = p a (f b) -> q c (f d) -> r s (f t) | |
firstOf :: Applicative f => (p a (f b) -> (c -> f c) -> (s -> f t)) -> p a (f b) -> s -> f t | |
firstOf l f = l f pure | |
{-# INLINE firstOf #-} | |
secondOf :: Applicative f => ((a -> f a) -> q c (f d) -> (s -> f t)) -> q c (f d) -> s -> f t | |
secondOf l = l pure | |
{-# INLINE secondOf #-} | |
bimapOf :: (Profunctor p, Profunctor q) => (p a (Identity b) -> q c (Identity d) -> s -> Identity t) -> p a b -> q c d -> s -> t | |
bimapOf l f g = runIdentity #. l (Identity #. f) (Identity #. g) | |
bifoldOf :: ((m -> Const m m) -> (m -> Const m m) -> s -> Const m s) -> s -> m | |
bifoldOf l = getConst #. l Const Const | |
bifoldMapOf :: (Profunctor p, Profunctor q) => (p a (Const m a) -> q b (Const m b) -> s -> Const m s) -> p a m -> q b m -> s -> m | |
bifoldMapOf l p q = getConst #. l (Const #. p) (Const #. q) | |
bifoldrOf :: (Profunctor p, Profunctor q => (p a (Const (Endo r) a) -> q c (Const (Endo r) c) -> s -> Const (Endo r) s) -> p a (r -> r) -> q c (r -> r) -> r -> s -> r | |
bifoldrOf l p q z = flip appEndo z `rmap` bifoldMapOf l (Endo #. p) (Endo #. q) | |
-- polylenses | |
type PolyLens s t a b = forall p. Strong p => p a b -> p s t | |
type PolyLens' s a = forall p. Strong p => p a a -> p s s | |
type PolyTraversal s t a b = forall f j. Applicative f => (forall i. a i -> f (b i)) -> s j -> f (t j) | |
type PolyTraversal' s a = forall f j. Applicative f => (forall i. a i -> f (a i)) -> s j -> f (s j) | |
type PolySetter s t a b = forall f j. Settable f => (forall i. a i -> f (b i)) -> s j -> f (t j) | |
type PolySetter' s a = forall f j. Settable f => (forall i. a i -> f (a i)) -> s j -> f (s j) | |
type PolyGetter s a = forall f j. (Functor f, Contravariant f) => (forall i. a i -> f (a i)) -> s j -> f (s j) | |
type PolyFold s a = forall f j. (Applicative f, Contravariant f) => (forall i. a i -> f (a i)) -> s j -> f (s j) | |
type PolyLensLike f s t a b = forall j. (forall i. a i -> f (b i)) -> s j -> f (t j) | |
type PolyLensLike' f s a = forall j. (forall i. a i -> f (a i)) -> s j -> f (s j) | |
type PolyPrism s t a b = forall p f j. (Choice p, Functor f) => (forall i. a i -> f (b i)) -> s j -> f (t j)) | |
bitraversed :: Bitraversable f => PolyTraversal (Un (f a c)) (Un (f b d)) (Bi a c) (Bi b d) | |
bitraversed = bi bitraverse | |
runUn :: Un a u -> a | |
runUn (Un a) = a | |
mono :: Functor f => LensLike f s t a b -> PolyLensLike f (Un s) (Un t) (Un a) (Un b) | |
mono l f (Un s) = Un <$> l (fmap runUn . f . Un) s | |
type Selector f s t a b = forall u. (a -> f b) -> s u -> f (t u) | |
poly :: Functor f => ((forall i. Un a i -> f (Un b i)) -> Un s '() -> f (Un t '())) -> LensLike f s t a b | |
poly l f s = runUn <$> l (\(Un a) -> Un <$> f a) (Un s) | |
bipoly :: Functor f => ((forall i. Bi a c i -> f (Bi b d i)) -> Un s '() -> f (Un t '())) -> Bioptic (->) (->) (->) f s t a b c d | |
bipoly l f g s = runUn <$> l (\xs -> case xs of L a -> L <$> f a; R b -> R <$> g b) (Un s) | |
bi :: Functor f => Bioptic (->) (->) (->) f s t a b c d -> PolyLensLike f (Un s) (Un t) (Bi a c) (Bi b d) | |
bi l f (Un s) = Un <$> l (\a -> f (L a) <&> \(L b) -> b) (\c -> f (R c) <&> \(R d) -> d) s | |
this :: PolyTraversal (Bi a c) (Bi b c) (Un a) (Un b) | |
this f (L a) = f (Un a) <&> \ (Un a) -> L a | |
this f (R b) = pure $ R b | |
that :: PolyTraversal (Bi c a) (Bi c b) (Un a) (Un b) | |
that f (L a) = pure $ L a | |
that f (R b) = f (Un b) <&> \(Un b) -> R b | |
these :: PolyLens (Bi a a) (Bi b b) (Un a) (Un b) | |
these f (L a) = f (Un a) <&> \ (Un a) -> L a | |
these f (R b) = f (Un b) <&> \ (Un b) -> R b | |
bitraverseOf :: Functor f => PolyLensLike f (Un s) (Un t) (Bi a c) (Bi b d) -> (a -> f b) -> (c -> f d) -> s -> f t | |
bitraverseOf l p q s = l (\xs -> case xs of | |
L a -> L <$> p a | |
R b -> R <$> q b) (Un s) <&> \(Un t) -> t | |
(?) :: PolyLensLike f s t a b -> PolyLensLike f a b c d -> PolyLensLike f s t c d | |
(?) f g x = f (g x) | |
class Compos t where | |
compos :: PolyTraversal' t t | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment