{-# language FlexibleInstances #-}
{-# language DeriveFunctor #-}
{-# language DeriveFoldable #-}
{-# language DeriveTraversable #-}
{-# language UndecidableInstances #-}
{-# language RankNTypes #-}
{-# language StandaloneDeriving #-}
module Data.Functor.Selection
  ( -- * Selection
  Selection(..)
  , Selection'
  , withUnwrapped
  -- ** Selecting/Deselecting
  -- | Most selection combinators require that both the selected and unselected types
  -- be equal (i.e. Selection f a a); this is necessary since items will switch
  -- their selection status. Your selected and unselected types may diverge, but
  -- you'll need to unify them in order to extract your underlying functor.
  , newSelection
  , runSelection
  , select
  , include
  , exclude
  , selectAll
  , deselectAll
  , invertSelection
  , mapSelected
  , mapUnselected
  , getSelected
  , getUnselected
  , unify
  , hoist
  ) where

import Control.Monad (ap)
-- import Control.Comonad (Comonad(..))
import Data.Foldable
import Data.Bifoldable (Bifoldable(..))
import Data.Bifunctor (Bifunctor(..))
import Data.Bitraversable (Bitraversable(..))

-- | A selection wraps a Functor @f@ and has an unselected type @b@ and a selected type @a@
newtype Selection f b a = Selection
  { -- | Expose the underlying representation of a 'Selection'
    Selection f b a -> f (Either b a)
unwrapSelection :: f (Either b a)
  } deriving (a -> Selection f b b -> Selection f b a
(a -> b) -> Selection f b a -> Selection f b b
(forall a b. (a -> b) -> Selection f b a -> Selection f b b)
-> (forall a b. a -> Selection f b b -> Selection f b a)
-> Functor (Selection f b)
forall a b. a -> Selection f b b -> Selection f b a
forall a b. (a -> b) -> Selection f b a -> Selection f b b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
forall (f :: * -> *) b a b.
Functor f =>
a -> Selection f b b -> Selection f b a
forall (f :: * -> *) b a b.
Functor f =>
(a -> b) -> Selection f b a -> Selection f b b
<$ :: a -> Selection f b b -> Selection f b a
$c<$ :: forall (f :: * -> *) b a b.
Functor f =>
a -> Selection f b b -> Selection f b a
fmap :: (a -> b) -> Selection f b a -> Selection f b b
$cfmap :: forall (f :: * -> *) b a b.
Functor f =>
(a -> b) -> Selection f b a -> Selection f b b
Functor, Selection f b a -> Bool
(a -> m) -> Selection f b a -> m
(a -> b -> b) -> b -> Selection f b a -> b
(forall m. Monoid m => Selection f b m -> m)
-> (forall m a. Monoid m => (a -> m) -> Selection f b a -> m)
-> (forall m a. Monoid m => (a -> m) -> Selection f b a -> m)
-> (forall a b. (a -> b -> b) -> b -> Selection f b a -> b)
-> (forall a b. (a -> b -> b) -> b -> Selection f b a -> b)
-> (forall b a. (b -> a -> b) -> b -> Selection f b a -> b)
-> (forall b a. (b -> a -> b) -> b -> Selection f b a -> b)
-> (forall a. (a -> a -> a) -> Selection f b a -> a)
-> (forall a. (a -> a -> a) -> Selection f b a -> a)
-> (forall a. Selection f b a -> [a])
-> (forall a. Selection f b a -> Bool)
-> (forall a. Selection f b a -> Int)
-> (forall a. Eq a => a -> Selection f b a -> Bool)
-> (forall a. Ord a => Selection f b a -> a)
-> (forall a. Ord a => Selection f b a -> a)
-> (forall a. Num a => Selection f b a -> a)
-> (forall a. Num a => Selection f b a -> a)
-> Foldable (Selection f b)
forall a. Eq a => a -> Selection f b a -> Bool
forall a. Num a => Selection f b a -> a
forall a. Ord a => Selection f b a -> a
forall m. Monoid m => Selection f b m -> m
forall a. Selection f b a -> Bool
forall a. Selection f b a -> Int
forall a. Selection f b a -> [a]
forall a. (a -> a -> a) -> Selection f b a -> a
forall m a. Monoid m => (a -> m) -> Selection f b a -> m
forall b a. (b -> a -> b) -> b -> Selection f b a -> b
forall a b. (a -> b -> b) -> b -> Selection f b a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
forall (f :: * -> *) b a.
(Foldable f, Eq a) =>
a -> Selection f b a -> Bool
forall (f :: * -> *) b a.
(Foldable f, Num a) =>
Selection f b a -> a
forall (f :: * -> *) b a.
(Foldable f, Ord a) =>
Selection f b a -> a
forall (f :: * -> *) b m.
(Foldable f, Monoid m) =>
Selection f b m -> m
forall (f :: * -> *) b a. Foldable f => Selection f b a -> Bool
forall (f :: * -> *) b a. Foldable f => Selection f b a -> Int
forall (f :: * -> *) b a. Foldable f => Selection f b a -> [a]
forall (f :: * -> *) b a.
Foldable f =>
(a -> a -> a) -> Selection f b a -> a
forall (f :: * -> *) b m a.
(Foldable f, Monoid m) =>
(a -> m) -> Selection f b a -> m
forall (f :: * -> *) b b a.
Foldable f =>
(b -> a -> b) -> b -> Selection f b a -> b
forall (f :: * -> *) b a b.
Foldable f =>
(a -> b -> b) -> b -> Selection f b a -> b
product :: Selection f b a -> a
$cproduct :: forall (f :: * -> *) b a.
(Foldable f, Num a) =>
Selection f b a -> a
sum :: Selection f b a -> a
$csum :: forall (f :: * -> *) b a.
(Foldable f, Num a) =>
Selection f b a -> a
minimum :: Selection f b a -> a
$cminimum :: forall (f :: * -> *) b a.
(Foldable f, Ord a) =>
Selection f b a -> a
maximum :: Selection f b a -> a
$cmaximum :: forall (f :: * -> *) b a.
(Foldable f, Ord a) =>
Selection f b a -> a
elem :: a -> Selection f b a -> Bool
$celem :: forall (f :: * -> *) b a.
(Foldable f, Eq a) =>
a -> Selection f b a -> Bool
length :: Selection f b a -> Int
$clength :: forall (f :: * -> *) b a. Foldable f => Selection f b a -> Int
null :: Selection f b a -> Bool
$cnull :: forall (f :: * -> *) b a. Foldable f => Selection f b a -> Bool
toList :: Selection f b a -> [a]
$ctoList :: forall (f :: * -> *) b a. Foldable f => Selection f b a -> [a]
foldl1 :: (a -> a -> a) -> Selection f b a -> a
$cfoldl1 :: forall (f :: * -> *) b a.
Foldable f =>
(a -> a -> a) -> Selection f b a -> a
foldr1 :: (a -> a -> a) -> Selection f b a -> a
$cfoldr1 :: forall (f :: * -> *) b a.
Foldable f =>
(a -> a -> a) -> Selection f b a -> a
foldl' :: (b -> a -> b) -> b -> Selection f b a -> b
$cfoldl' :: forall (f :: * -> *) b b a.
Foldable f =>
(b -> a -> b) -> b -> Selection f b a -> b
foldl :: (b -> a -> b) -> b -> Selection f b a -> b
$cfoldl :: forall (f :: * -> *) b b a.
Foldable f =>
(b -> a -> b) -> b -> Selection f b a -> b
foldr' :: (a -> b -> b) -> b -> Selection f b a -> b
$cfoldr' :: forall (f :: * -> *) b a b.
Foldable f =>
(a -> b -> b) -> b -> Selection f b a -> b
foldr :: (a -> b -> b) -> b -> Selection f b a -> b
$cfoldr :: forall (f :: * -> *) b a b.
Foldable f =>
(a -> b -> b) -> b -> Selection f b a -> b
foldMap' :: (a -> m) -> Selection f b a -> m
$cfoldMap' :: forall (f :: * -> *) b m a.
(Foldable f, Monoid m) =>
(a -> m) -> Selection f b a -> m
foldMap :: (a -> m) -> Selection f b a -> m
$cfoldMap :: forall (f :: * -> *) b m a.
(Foldable f, Monoid m) =>
(a -> m) -> Selection f b a -> m
fold :: Selection f b m -> m
$cfold :: forall (f :: * -> *) b m.
(Foldable f, Monoid m) =>
Selection f b m -> m
Foldable, Functor (Selection f b)
Foldable (Selection f b)
(Functor (Selection f b), Foldable (Selection f b)) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> Selection f b a -> f (Selection f b b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    Selection f b (f a) -> f (Selection f b a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Selection f b a -> m (Selection f b b))
-> (forall (m :: * -> *) a.
    Monad m =>
    Selection f b (m a) -> m (Selection f b a))
-> Traversable (Selection f b)
(a -> f b) -> Selection f b a -> f (Selection f b b)
forall (t :: * -> *).
(Functor t, Foldable t) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
Selection f b (m a) -> m (Selection f b a)
forall (f :: * -> *) a.
Applicative f =>
Selection f b (f a) -> f (Selection f b a)
forall (f :: * -> *) b. Traversable f => Functor (Selection f b)
forall (f :: * -> *) b. Traversable f => Foldable (Selection f b)
forall (f :: * -> *) b (m :: * -> *) a.
(Traversable f, Monad m) =>
Selection f b (m a) -> m (Selection f b a)
forall (f :: * -> *) b (f :: * -> *) a.
(Traversable f, Applicative f) =>
Selection f b (f a) -> f (Selection f b a)
forall (f :: * -> *) b (m :: * -> *) a b.
(Traversable f, Monad m) =>
(a -> m b) -> Selection f b a -> m (Selection f b b)
forall (f :: * -> *) b (f :: * -> *) a b.
(Traversable f, Applicative f) =>
(a -> f b) -> Selection f b a -> f (Selection f b b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Selection f b a -> m (Selection f b b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Selection f b a -> f (Selection f b b)
sequence :: Selection f b (m a) -> m (Selection f b a)
$csequence :: forall (f :: * -> *) b (m :: * -> *) a.
(Traversable f, Monad m) =>
Selection f b (m a) -> m (Selection f b a)
mapM :: (a -> m b) -> Selection f b a -> m (Selection f b b)
$cmapM :: forall (f :: * -> *) b (m :: * -> *) a b.
(Traversable f, Monad m) =>
(a -> m b) -> Selection f b a -> m (Selection f b b)
sequenceA :: Selection f b (f a) -> f (Selection f b a)
$csequenceA :: forall (f :: * -> *) b (f :: * -> *) a.
(Traversable f, Applicative f) =>
Selection f b (f a) -> f (Selection f b a)
traverse :: (a -> f b) -> Selection f b a -> f (Selection f b b)
$ctraverse :: forall (f :: * -> *) b (f :: * -> *) a b.
(Traversable f, Applicative f) =>
(a -> f b) -> Selection f b a -> f (Selection f b b)
$cp2Traversable :: forall (f :: * -> *) b. Traversable f => Foldable (Selection f b)
$cp1Traversable :: forall (f :: * -> *) b. Traversable f => Functor (Selection f b)
Traversable)

-- | A type alias for selections with the same unselected/selected types
type Selection' f a = Selection f a a

deriving instance (Show (f (Either b a))) => Show (Selection f b a)
deriving instance (Eq (f (Either b a))) => Eq (Selection f b a)

instance Monad m => Applicative (Selection m b) where
  pure :: a -> Selection m b a
pure = m (Either b a) -> Selection m b a
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (m (Either b a) -> Selection m b a)
-> (a -> m (Either b a)) -> a -> Selection m b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either b a -> m (Either b a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either b a -> m (Either b a))
-> (a -> Either b a) -> a -> m (Either b a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either b a
forall a b. b -> Either a b
Right
  <*> :: Selection m b (a -> b) -> Selection m b a -> Selection m b b
(<*>) = Selection m b (a -> b) -> Selection m b a -> Selection m b b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

-- | Selection is a monad over selected items when the underlying m is a Monad
instance (Monad m) => Monad (Selection m b) where
  return :: a -> Selection m b a
return = a -> Selection m b a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  Selection m :: m (Either b a)
m >>= :: Selection m b a -> (a -> Selection m b b) -> Selection m b b
>>= k :: a -> Selection m b b
k =
    m (Either b b) -> Selection m b b
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (m (Either b b) -> Selection m b b)
-> m (Either b b) -> Selection m b b
forall a b. (a -> b) -> a -> b
$ m (Either b a)
m m (Either b a) -> (Either b a -> m (Either b b)) -> m (Either b b)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (b -> m (Either b b))
-> (a -> m (Either b b)) -> Either b a -> m (Either b b)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Either b b -> m (Either b b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either b b -> m (Either b b))
-> (b -> Either b b) -> b -> m (Either b b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Either b b
forall a b. a -> Either a b
Left) (Selection m b b -> m (Either b b)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection (Selection m b b -> m (Either b b))
-> (a -> Selection m b b) -> a -> m (Either b b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Selection m b b
k)

-- | Bifunctor over unselected ('first') and selected ('second') values
instance (Functor f) => Bifunctor (Selection f) where
  first :: (a -> b) -> Selection f a c -> Selection f b c
first f :: a -> b
f = f (Either b c) -> Selection f b c
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (f (Either b c) -> Selection f b c)
-> (Selection f a c -> f (Either b c))
-> Selection f a c
-> Selection f b c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either a c -> Either b c) -> f (Either a c) -> f (Either b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f) (f (Either a c) -> f (Either b c))
-> (Selection f a c -> f (Either a c))
-> Selection f a c
-> f (Either b c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f a c -> f (Either a c)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection
  second :: (b -> c) -> Selection f a b -> Selection f a c
second = (b -> c) -> Selection f a b -> Selection f a c
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- | Bifoldable over unselected and selected values respectively
instance (Foldable f) => Bifoldable (Selection f) where
  bifoldMap :: (a -> m) -> (b -> m) -> Selection f a b -> m
bifoldMap l :: a -> m
l r :: b -> m
r = (Either a b -> m) -> f (Either a b) -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ((a -> m) -> (b -> m) -> Either a b -> m
forall (p :: * -> * -> *) m a b.
(Bifoldable p, Monoid m) =>
(a -> m) -> (b -> m) -> p a b -> m
bifoldMap a -> m
l b -> m
r) (f (Either a b) -> m)
-> (Selection f a b -> f (Either a b)) -> Selection f a b -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f a b -> f (Either a b)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection

-- | Bitraversable over unselected and selected values respectively
instance (Traversable f) => Bitraversable (Selection f) where
  bitraverse :: (a -> f c) -> (b -> f d) -> Selection f a b -> f (Selection f c d)
bitraverse l :: a -> f c
l r :: b -> f d
r = (f (Either c d) -> Selection f c d)
-> f (f (Either c d)) -> f (Selection f c d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap f (Either c d) -> Selection f c d
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (f (f (Either c d)) -> f (Selection f c d))
-> (Selection f a b -> f (f (Either c d)))
-> Selection f a b
-> f (Selection f c d)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either a b -> f (Either c d))
-> f (Either a b) -> f (f (Either c d))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((a -> f c) -> (b -> f d) -> Either a b -> f (Either c d)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bitraverse a -> f c
l b -> f d
r) (f (Either a b) -> f (f (Either c d)))
-> (Selection f a b -> f (Either a b))
-> Selection f a b
-> f (f (Either c d))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f a b -> f (Either a b)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection

-- | Modify the underlying representation of a selection
--
-- A powerful and low-level way to transform your selection
withUnwrapped :: (Functor f) => (f (Either b a) -> g (Either d c)) -> Selection f b a -> Selection g d c
withUnwrapped :: (f (Either b a) -> g (Either d c))
-> Selection f b a -> Selection g d c
withUnwrapped f :: f (Either b a) -> g (Either d c)
f = g (Either d c) -> Selection g d c
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (g (Either d c) -> Selection g d c)
-> (Selection f b a -> g (Either d c))
-> Selection f b a
-> Selection g d c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f (Either b a) -> g (Either d c)
f (f (Either b a) -> g (Either d c))
-> (Selection f b a -> f (Either b a))
-> Selection f b a
-> g (Either d c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f b a -> f (Either b a)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection

-- | Modify the underlying representation of a selection
--
-- A powerful and low-level way to transform your selection
reselect :: (Functor f) => (Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect :: (Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect f :: Either b a -> Either d c
f = (f (Either b a) -> f (Either d c))
-> Selection f b a -> Selection f d c
forall (f :: * -> *) b a (g :: * -> *) d c.
Functor f =>
(f (Either b a) -> g (Either d c))
-> Selection f b a -> Selection g d c
withUnwrapped ((Either b a -> Either d c) -> f (Either b a) -> f (Either d c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either b a -> Either d c
f)

-- | Create a selection from a functor by selecting all values
newSelection :: (Functor f) => f a -> Selection f b a
newSelection :: f a -> Selection f b a
newSelection = f (Either b a) -> Selection f b a
forall (f :: * -> *) b a. f (Either b a) -> Selection f b a
Selection (f (Either b a) -> Selection f b a)
-> (f a -> f (Either b a)) -> f a -> Selection f b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Either b a) -> f a -> f (Either b a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Either b a
forall a b. b -> Either a b
Right

-- | Drops selection from your functor returning all values (selected or not).
--
-- @'forgetSelection' . 'newSelection' = id@
--
-- @'forgetSelection' = 'unify' id id@
runSelection :: (Functor f) => Selection f a a -> f a
runSelection :: Selection f a a -> f a
runSelection = (a -> a) -> (a -> a) -> Selection f a a -> f a
forall (f :: * -> *) b c a.
Functor f =>
(b -> c) -> (a -> c) -> Selection f b a -> f c
unify a -> a
forall a. a -> a
id a -> a
forall a. a -> a
id

-- | Clear the selection then select only items which match a predicate.
--
-- @'select' f = 'include' f . 'deselectAll'@
select :: (Functor f) => (a -> Bool) -> Selection f a a -> Selection f a a
select :: (a -> Bool) -> Selection f a a -> Selection f a a
select f :: a -> Bool
f = (a -> Bool) -> Selection f a a -> Selection f a a
forall (f :: * -> *) a.
Functor f =>
(a -> Bool) -> Selection f a a -> Selection f a a
include a -> Bool
f (Selection f a a -> Selection f a a)
-> (Selection f a a -> Selection f a a)
-> Selection f a a
-> Selection f a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f a a -> Selection f a a
forall (f :: * -> *) b a.
Functor f =>
Selection f b b -> Selection f b a
deselectAll


-- | Add items which match a predicate to the current selection
--
-- @'include' f . 'select' g = 'select' (\a -> f a || g a)@
include :: (Functor f) => (a -> Bool) -> Selection f a a -> Selection f a a
include :: (a -> Bool) -> Selection f a a -> Selection f a a
include f :: a -> Bool
f = (Either a a -> Either a a) -> Selection f a a -> Selection f a a
forall (f :: * -> *) b a d c.
Functor f =>
(Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect ((a -> Either a a) -> (a -> Either a a) -> Either a a -> Either a a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((a -> Bool) -> a -> Either a a
forall a. (a -> Bool) -> a -> Either a a
choose a -> Bool
f) a -> Either a a
forall a b. b -> Either a b
Right)

-- | Remove items which match a predicate to the current selection
--
-- @'exclude' f . 'select' g = 'select' (\a -> f a && not (g a))@
exclude :: (Functor f) => (a -> Bool) -> Selection f a a -> Selection f a a
exclude :: (a -> Bool) -> Selection f a a -> Selection f a a
exclude f :: a -> Bool
f = (Either a a -> Either a a) -> Selection f a a -> Selection f a a
forall (f :: * -> *) b a d c.
Functor f =>
(Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect ((a -> Either a a) -> (a -> Either a a) -> Either a a -> Either a a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> Either a a
forall a b. a -> Either a b
Left (Either a a -> Either a a
forall a b. Either a b -> Either b a
switch (Either a a -> Either a a) -> (a -> Either a a) -> a -> Either a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Bool) -> a -> Either a a
forall a. (a -> Bool) -> a -> Either a a
choose a -> Bool
f))

-- | Select all items in the container
--
-- @'selectAll' = 'include' (const True)@
selectAll :: (Functor f) => Selection f a a -> Selection f b a
selectAll :: Selection f a a -> Selection f b a
selectAll = (Either a a -> Either b a) -> Selection f a a -> Selection f b a
forall (f :: * -> *) b a d c.
Functor f =>
(Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect (a -> Either b a
forall a b. b -> Either a b
Right (a -> Either b a) -> (Either a a -> a) -> Either a a -> Either b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> (a -> a) -> Either a a -> a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> a
forall a. a -> a
id a -> a
forall a. a -> a
id)

-- | Deselect all items in the container
--
-- @'deselectAll' = 'exclude' (const True)@
deselectAll :: (Functor f) => Selection f b b -> Selection f b a
deselectAll :: Selection f b b -> Selection f b a
deselectAll = (Either b b -> Either b a) -> Selection f b b -> Selection f b a
forall (f :: * -> *) b a d c.
Functor f =>
(Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect (b -> Either b a
forall a b. a -> Either a b
Left (b -> Either b a) -> (Either b b -> b) -> Either b b -> Either b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> b) -> (b -> b) -> Either b b -> b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either b -> b
forall a. a -> a
id b -> b
forall a. a -> a
id)

-- | Flip the selection, all selected are now unselected and vice versa.
invertSelection :: (Functor f) => Selection f b a -> Selection f a b
invertSelection :: Selection f b a -> Selection f a b
invertSelection = (Either b a -> Either a b) -> Selection f b a -> Selection f a b
forall (f :: * -> *) b a d c.
Functor f =>
(Either b a -> Either d c) -> Selection f b a -> Selection f d c
reselect Either b a -> Either a b
forall a b. Either a b -> Either b a
switch

-- | Map over selected values
--
-- @'mapSelected' = fmap@
mapSelected :: (Functor f) => (a -> c) -> Selection f b a -> Selection f b c
mapSelected :: (a -> c) -> Selection f b a -> Selection f b c
mapSelected = (a -> c) -> Selection f b a -> Selection f b c
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- | Map over unselected values
--
-- @'mapUnselected' = 'first'@
mapUnselected :: (Functor f) => (b -> c) -> Selection f b a -> Selection f c a
mapUnselected :: (b -> c) -> Selection f b a -> Selection f c a
mapUnselected = (b -> c) -> Selection f b a -> Selection f c a
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first

-- | Collect all selected values into a list.
--
-- @'getSelected' = toList@
getSelected :: (Foldable f) => Selection f b a -> [a]
getSelected :: Selection f b a -> [a]
getSelected = Selection f b a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- | Collect all unselected values into a list. For more complex operations use
-- operations from Bifoldable.
--
-- @'getUnselected' = 'getSelected' . 'invertSelection'@
getUnselected :: (Foldable f, Functor f) => Selection f b a -> [b]
getUnselected :: Selection f b a -> [b]
getUnselected = Selection f a b -> [b]
forall (f :: * -> *) b a. Foldable f => Selection f b a -> [a]
getSelected (Selection f a b -> [b])
-> (Selection f b a -> Selection f a b) -> Selection f b a -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f b a -> Selection f a b
forall (f :: * -> *) b a.
Functor f =>
Selection f b a -> Selection f a b
invertSelection

-- | Unify selected and unselected and forget the selection
--
-- @'unify' f g == 'forgetSelection' . 'onUnselected' f . 'onSelected' g@
unify :: (Functor f) => (b -> c) -> (a -> c) -> Selection f b a -> f c
unify :: (b -> c) -> (a -> c) -> Selection f b a -> f c
unify l :: b -> c
l r :: a -> c
r = (Either b a -> c) -> f (Either b a) -> f c
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((b -> c) -> (a -> c) -> Either b a -> c
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either b -> c
l a -> c
r) (f (Either b a) -> f c)
-> (Selection f b a -> f (Either b a)) -> Selection f b a -> f c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selection f b a -> f (Either b a)
forall (f :: * -> *) b a. Selection f b a -> f (Either b a)
unwrapSelection

-- | Perform a natural transformation over the underlying container of a selectable
hoist :: (Functor f) => (forall c. f c -> g c) -> Selection f b a -> Selection g b a
hoist :: (forall c. f c -> g c) -> Selection f b a -> Selection g b a
hoist f :: forall c. f c -> g c
f = (f (Either b a) -> g (Either b a))
-> Selection f b a -> Selection g b a
forall (f :: * -> *) b a (g :: * -> *) d c.
Functor f =>
(f (Either b a) -> g (Either d c))
-> Selection f b a -> Selection g d c
withUnwrapped f (Either b a) -> g (Either b a)
forall c. f c -> g c
f

-- Comonad combinators

-- | Select values based on their context within a comonad. This combinator makes
-- its selection by running the predicate using extend.
-- selectWithContext :: (Comonad w) => (w a -> Bool) -> Selection w a a -> Selection w a a
-- selectWithContext f = withUnwrapped (extend (choose' extract f) .  fmap (either id id))


-- Helpers
choose' :: (a -> b) -> (a -> Bool) -> a -> Either b b
choose' :: (a -> b) -> (a -> Bool) -> a -> Either b b
choose' f :: a -> b
f p :: a -> Bool
p a :: a
a =
    if a -> Bool
p a
a
        then b -> Either b b
forall a b. b -> Either a b
Right (a -> b
f a
a)
        else b -> Either b b
forall a b. a -> Either a b
Left (a -> b
f a
a)

choose :: (a -> Bool) -> a -> Either a a
choose :: (a -> Bool) -> a -> Either a a
choose = (a -> a) -> (a -> Bool) -> a -> Either a a
forall a b. (a -> b) -> (a -> Bool) -> a -> Either b b
choose' a -> a
forall a. a -> a
id

switch :: Either a b -> Either b a
switch :: Either a b -> Either b a
switch = (a -> Either b a) -> (b -> Either b a) -> Either a b -> Either b a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> Either b a
forall a b. b -> Either a b
Right b -> Either b a
forall a b. a -> Either a b
Left