packages feed

proton-0.0.2: src/Proton/Traversal.hs

{-# LANGUAGE TupleSections #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Proton.Traversal where

import Control.Applicative
import Control.Monad.State
import Data.Bitraversable
import Data.Profunctor
import Data.Profunctor.Rep
import Data.Profunctor.Sieve
import Data.Profunctor.Traversing
import Proton.Fold
import Proton.Lens
import Proton.Setter
import Proton.Types

type Traversal s t a b = forall p. (Traversing p) => p a b -> p s t
type Traversal' s a = forall p. Traversing p => p a a -> p s s

traversed :: Traversable f => Traversal (f a) (f b) a b
traversed = traverse'

filtered :: (a -> Bool) -> Traversal' a a
filtered predicate = dimap partition (either id id) . left'
  where
    partition a
        | predicate a = Left a
        | otherwise = Right a

traverseOf :: Optic (Star f) s t a b -> (a -> f b) -> s -> f t
traverseOf t = runStar . t . Star

infixr 4 %%~
(%%~) :: Optic (Star f) s t a b -> (a -> f b) -> s -> f t
(%%~) = traverseOf

beside :: forall s t a b s' t' p r. (Representable p, Bitraversable r, Applicative (Rep p)) => Optic p s t a b -> Optic p s' t' a b -> Optic p (r s s') (r t t') a b
beside t1 t2 p = tabulate go
  where
    go :: r s s' -> Rep p (r t t')
    go rss = bitraverse (sieve $ t1 p) (sieve $ t2 p) rss


unsafePartsOf :: forall s t a b. (forall p. Traversing p => p a b -> p s t) -> Lens s t [a] [b]
unsafePartsOf t = lens getter setter'
  where
    getter :: s -> [a]
    getter = toListOf t
    setter' :: s -> [b] -> t
    setter' s bs = flip evalState bs $ traverseOf t insert s
    insert :: x -> State [b] b
    insert _ = gets head <* modify tail

partsOf :: forall s a. (forall p. Traversing p => p a a -> p s s) -> Lens' s [a]
partsOf t = lens getter setter'
  where
    getter :: s -> [a]
    getter = toListOf t
    setter' :: s -> [a] -> s
    setter' s as =
        set (unsafePartsOf t) s (getZipList (ZipList as <|> ZipList (getter s)))

taking :: forall q s a. Traversing q => Int -> (forall p. Traversing p => p a a -> p s s) -> Optic' q s a
taking n t = partsOf t . wander go
  where
    go :: forall f x. Applicative f => (x -> f x) -> [x] -> f [x]
    go handler as =
      case splitAt n as of
        (prefix, suffix) -> liftA2 (<>) (traverse handler prefix) (pure suffix)

dropping :: forall s a. Int -> Traversal' s a -> Traversal' s a
dropping n t = partsOf t . wander go
  where
    go :: Applicative f => (a -> f a) -> [a] -> f [a]
    go handler as =
      case splitAt n as of
        (prefix, suffix) -> liftA2 (<>) (pure prefix) (traverse handler suffix)


-- failing :: (forall p. Traversing p => p a b -> p s t) -> (forall p. Traversing p => p a b -> p s t) -> (Traversing p => p a b -> p s t)
-- failing f _ pab = undefined $ foldMapOf f (const (Sum 1))
    -- _ $ traverse' @_ @[] p

-- both
-- failing ()