{-# LANGUAGE ScopedTypeVariables #-}
module Data.List.PointedList.Extras
  ( filterr
  , catMaybesr
  ) where

import           Control.Monad                (guard)
import           Data.List.PointedList        (PointedList(..))
import qualified Data.Maybe            as M   (catMaybes)

-- | filter a pointed list, preferring the right list as the new focus if the focus is lost.
filterr :: (a -> Bool) -> PointedList a -> Maybe (PointedList a)
filterr :: (a -> Bool) -> PointedList a -> Maybe (PointedList a)
filterr a -> Bool
filt PointedList a
pl = PointedList (Maybe a) -> Maybe (PointedList a)
forall a. PointedList (Maybe a) -> Maybe (PointedList a)
catMaybesr (PointedList (Maybe a) -> Maybe (PointedList a))
-> PointedList (Maybe a) -> Maybe (PointedList a)
forall a b. (a -> b) -> a -> b
$ (a -> Maybe a) -> PointedList a -> PointedList (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
a -> Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (a -> Bool
filt a
a) Maybe () -> Maybe a -> Maybe a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> Maybe a
forall a. a -> Maybe a
Just a
a) PointedList a
pl

-- | catMaybes on a pointed list, preferring the right list as the new focus if the focus is lost.
catMaybesr :: forall a . PointedList (Maybe a) -> Maybe (PointedList a)
catMaybesr :: PointedList (Maybe a) -> Maybe (PointedList a)
catMaybesr (PointedList [Maybe a]
mls Maybe a
mf [Maybe a]
mrs) = case Maybe a
mf of
  Maybe a
Nothing -> [a] -> [a] -> Maybe (PointedList a)
shiftFocus [a]
rs [a]
ss
  Just a
f  -> PointedList a -> Maybe (PointedList a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PointedList a -> Maybe (PointedList a))
-> PointedList a -> Maybe (PointedList a)
forall a b. (a -> b) -> a -> b
$ [a] -> a -> [a] -> PointedList a
forall a. [a] -> a -> [a] -> PointedList a
PointedList [a]
rs a
f [a]
ss
 where
  rs, ss :: [a]
  rs :: [a]
rs = [Maybe a] -> [a]
forall a. [Maybe a] -> [a]
M.catMaybes [Maybe a]
mls
  ss :: [a]
ss = [Maybe a] -> [a]
forall a. [Maybe a] -> [a]
M.catMaybes [Maybe a]
mrs

  shiftFocus :: [a] -> [a] -> Maybe (PointedList a)
  shiftFocus :: [a] -> [a] -> Maybe (PointedList a)
shiftFocus []     (a
f:[a]
rs) = PointedList a -> Maybe (PointedList a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PointedList a -> Maybe (PointedList a))
-> PointedList a -> Maybe (PointedList a)
forall a b. (a -> b) -> a -> b
$ [a] -> a -> [a] -> PointedList a
forall a. [a] -> a -> [a] -> PointedList a
PointedList [] a
f [a]
rs
  shiftFocus (a
f:[a]
ls) []     = PointedList a -> Maybe (PointedList a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PointedList a -> Maybe (PointedList a))
-> PointedList a -> Maybe (PointedList a)
forall a b. (a -> b) -> a -> b
$ [a] -> a -> [a] -> PointedList a
forall a. [a] -> a -> [a] -> PointedList a
PointedList [a]
ls a
f []
  shiftFocus [a]
_      [a]
_      = Maybe (PointedList a)
forall a. Maybe a
Nothing