{-# LANGUAGE CPP                   #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE TypeFamilies          #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.RAVec.Lens (
    -- * Indexing
    ix,
    ) where

import Control.Applicative ((<$>))
import Data.Bin.Pos        (Pos (..))
import Prelude ()

import qualified Control.Lens             as L
import qualified Data.RAVec.NonEmpty.Lens as NE

import Data.RAVec

-- $setup
-- >>> import Control.Lens ((^.), (&), (.~), (^?), (#))
-- >>> import Prelude
-- >>> import Data.RAVec
-- >>> import qualified Data.Type.Bin as B

-------------------------------------------------------------------------------
-- Indexing
-------------------------------------------------------------------------------

-- | Index lens.
--
-- >>> let Just ral = fromList "xyz" :: Maybe (RAVec B.Bin3 Char)
-- >>> ral & ix maxBound .~ 'Z'
-- NonEmpty (NE (Cons1 (Leaf 'x') (Last (Node (Leaf 'y') (Leaf 'Z')))))
ix :: Pos b -> L.Lens' (RAVec b a) a
ix :: Pos b -> Lens' (RAVec b a) a
ix (Pos PosP b1
n) a -> f a
f (NonEmpty NERAVec b1 a
x) = NERAVec b1 a -> RAVec ('BP b1) a
forall (b1 :: BinP) a. NERAVec b1 a -> RAVec ('BP b1) a
NonEmpty (NERAVec b1 a -> RAVec ('BP b1) a)
-> f (NERAVec b1 a) -> f (RAVec ('BP b1) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PosP b1 -> (a -> f a) -> NERAVec b1 a -> f (NERAVec b1 a)
forall (b :: BinP) a. PosP b -> Lens' (NERAVec b a) a
NE.ix PosP b1
n a -> f a
f NERAVec b1 a
NERAVec b1 a
x

-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------

#if !MIN_VERSION_lens(5,0,0)
instance L.FunctorWithIndex (Pos b) (RAVec b) where
    imap = imap

instance L.FoldableWithIndex (Pos b) (RAVec b) where
    ifoldMap = ifoldMap
    ifoldr   = ifoldr

instance L.TraversableWithIndex (Pos b) (RAVec b) where
    itraverse = itraverse
#endif

instance L.Each (RAVec n a) (RAVec n b) a b where
    each :: (a -> f b) -> RAVec n a -> f (RAVec n b)
each = (a -> f b) -> RAVec n a -> f (RAVec n b)
forall (f :: * -> *) a b (n :: Bin).
Applicative f =>
(a -> f b) -> RAVec n a -> f (RAVec n b)
traverse

type instance L.Index   (RAVec n a) = Pos n
type instance L.IxValue (RAVec n a) = a

instance L.Ixed (RAVec b a) where
    ix :: Index (RAVec b a) -> Traversal' (RAVec b a) (IxValue (RAVec b a))
ix Index (RAVec b a)
i = Pos b -> Lens' (RAVec b a) a
forall (b :: Bin) a. Pos b -> Lens' (RAVec b a) a
ix Pos b
Index (RAVec b a)
i