module Lens.Family.Clone
( cloneLens, cloneTraversal, cloneSetter, cloneGetter, cloneFold
, ALens, ALens'
, ATraversal, ATraversal'
, AGetter, AGetter'
, AFold, AFold'
, IStore, IKleeneStore
, LensLike, LensLike', FoldLike, FoldLike', ASetter
, Applicative, Phantom, Identical
) where
import Control.Applicative (Applicative, pure, (<*>), (<$>))
import Lens.Family.Unchecked (Identical, setting)
import Lens.Family ( LensLike, LensLike'
, ASetter, over
, FoldLike, FoldLike', toListOf, folding
, to, view
, Phantom
)
data IStore b b' a = IStore (b' -> a) b
instance Functor (IStore b b') where
fmap f (IStore g b) = IStore (f . g) b
type ALens a a' b b' = LensLike (IStore b b') a a' b b'
type ALens' a b = LensLike' (IStore b b) a b
cloneLens :: Functor f => ALens a a' b b' -> LensLike f a a' b b'
cloneLens univ f = experiment f . univ (IStore id)
experiment :: Functor f => (b -> f b') -> IStore b b' a -> f a
experiment f (IStore g b) = g <$> f b
data IKleeneStore b b' a = Unit a
| Battery (IKleeneStore b b' (b' -> a)) b
instance Functor (IKleeneStore b b') where
fmap f (Unit a) = Unit (f a)
fmap f (Battery g b) = Battery (fmap (f .) g) b
instance Applicative (IKleeneStore b b') where
pure = Unit
Unit f <*> a = fmap f a
Battery f b <*> a = Battery (flip <$> f <*> a) b
type ATraversal a a' b b' = LensLike (IKleeneStore b b') a a' b b'
type ATraversal' a b = LensLike' (IKleeneStore b b) a b
cloneTraversal :: Applicative f => ATraversal a a' b b' -> LensLike f a a' b b'
cloneTraversal univ f = research f . univ (Battery (Unit id))
research :: Applicative f => (b -> f b') -> IKleeneStore b b' a -> f a
research _ (Unit a) = pure a
research f (Battery g b) = research f g <*> f b
cloneSetter :: Identical f => ASetter a a' b b' -> LensLike f a a' b b'
cloneSetter = setting . over
type AFold a a' b b' = FoldLike [b] a a' b b'
type AFold' a b = FoldLike' [b] a b
cloneFold :: (Phantom f, Applicative f) => AFold a a' b b' -> LensLike f a a' b b'
cloneFold univ = folding (toListOf univ)
type AGetter a a' b b' = FoldLike b a a' b b'
type AGetter' a b = FoldLike' b a b
cloneGetter :: Phantom f => AGetter a a' b b' -> LensLike f a a' b b'
cloneGetter univ = to (view univ)