{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}

{- |
Module      : Primus.Lens
Description : minimal lens interfaces
-}
module Primus.Lens (
  Lens,
  Lens',
  lens,
  Iso,
  Iso',
  iso,
  Traversal,
  _Fst,
  _Snd,
) where

import Data.Profunctor

-- | lens type synonym
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t

-- | simpler lens type synonym
type Lens' s a = Lens s s a a

-- | create a lens
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens s -> a
sa s -> b -> t
sbt a -> f b
afb s
s = s -> b -> t
sbt s
s (b -> t) -> f b -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
afb (s -> a
sa s
s)
{-# INLINE lens #-}

-- | isomorphism type synonym
type Iso s t a b = forall p f. (Profunctor p, Functor f) => p a (f b) -> p s (f t)

-- | simpler isomorphism type synonym
type Iso' s a = Iso s s a a

-- | create an isomoprhism
iso :: (s -> a) -> (b -> t) -> Iso s t a b
iso :: (s -> a) -> (b -> t) -> Iso s t a b
iso s -> a
sa b -> t
bt = (s -> a) -> (f b -> f t) -> p a (f b) -> p s (f t)
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap s -> a
sa ((b -> t) -> f b -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt)
{-# INLINE iso #-}

-- | traversal type synonym
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t

-- | lens for accessing the first value in a tuple
_Fst :: forall a x a'. Lens (a, x) (a', x) a a'
_Fst :: (a -> f a') -> (a, x) -> f (a', x)
_Fst = ((a, x) -> a)
-> ((a, x) -> a' -> (a', x)) -> Lens (a, x) (a', x) a a'
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (a, x) -> a
forall a b. (a, b) -> a
fst (\(a
_, x
x) a'
a' -> (a'
a', x
x))
{-# INLINE _Fst #-}

-- | lens for accessing the second value in a tuple
_Snd :: forall x b b'. Lens (x, b) (x, b') b b'
_Snd :: (b -> f b') -> (x, b) -> f (x, b')
_Snd = ((x, b) -> b)
-> ((x, b) -> b' -> (x, b')) -> Lens (x, b) (x, b') b b'
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (x, b) -> b
forall a b. (a, b) -> b
snd (\(x
x, b
_) b'
b' -> (x
x, b'
b'))
{-# INLINE _Snd #-}