{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ExistentialQuantification #-}
#ifdef TRUSTWORTHY
{-# LANGUAGE Trustworthy #-}
#endif

#ifndef MIN_VERSION_base
#define MIN_VERSION_base(x,y,z) 1
#endif

-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Zipper.Internal
-- Copyright   :  (C) 2012-2013 Edward Kmett
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  experimental
-- Portability :  non-portable
--
-- This module provides internal types and functions used in the implementation
-- of @Control.Zipper@. You shouldn't need to import it directly, and the
-- exported types can be used to break 'Zipper' invariants.
--
----------------------------------------------------------------------------
module Control.Zipper.Internal where

import Control.Applicative
import Control.Category ((>>>))
import Control.Monad
import qualified Control.Monad.Fail as Fail
import Control.Lens.Getter
import Control.Lens.Internal.Context
import Control.Lens.Internal.Indexed
import Control.Lens.Lens
import Control.Lens.Setter
import Control.Lens.Traversal
import Control.Lens.Type
import Data.Foldable.WithIndex
import Data.Functor.Apply
import Data.Functor.WithIndex
import Data.Maybe
import Data.Monoid (Last(..))
import Data.Profunctor.Unsafe
import Data.Traversable.WithIndex

#if !(MIN_VERSION_base(4,11,0))
import Data.Semigroup (Semigroup(..))
#endif

#if !MIN_VERSION_lens(5,0,0)
import qualified Control.Lens.Indexed as Lens
#endif

-- $setup
-- >>> :set -XNoOverloadedStrings
-- >>> import Control.Lens
-- >>> import Data.Char
-- >>> import Data.Maybe (isNothing)

------------------------------------------------------------------------------
-- * Jacket
------------------------------------------------------------------------------

-- | A 'Jacket' is used to store the contents of a 'Traversal' in a way
-- that we do not have to re-asocciate the elements. This enables us to
-- more gracefully deal with infinite traversals.
data Jacket i a
  = Ap Int         -- size
       Bool        -- left-to-right null check
       Bool        -- right-to-left null check
       (Last i)
       (Jacket i a) -- left
       (Jacket i a) -- right
  | Leaf i a
  | Pure
  deriving Int -> Jacket i a -> ShowS
[Jacket i a] -> ShowS
Jacket i a -> String
(Int -> Jacket i a -> ShowS)
-> (Jacket i a -> String)
-> ([Jacket i a] -> ShowS)
-> Show (Jacket i a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall i a. (Show i, Show a) => Int -> Jacket i a -> ShowS
forall i a. (Show i, Show a) => [Jacket i a] -> ShowS
forall i a. (Show i, Show a) => Jacket i a -> String
showList :: [Jacket i a] -> ShowS
$cshowList :: forall i a. (Show i, Show a) => [Jacket i a] -> ShowS
show :: Jacket i a -> String
$cshow :: forall i a. (Show i, Show a) => Jacket i a -> String
showsPrec :: Int -> Jacket i a -> ShowS
$cshowsPrec :: forall i a. (Show i, Show a) => Int -> Jacket i a -> ShowS
Show

-- | Return the number of children in a jacket
size :: Jacket i a -> Int
size :: Jacket i a -> Int
size (Ap Int
s Bool
_ Bool
_ Last i
_ Jacket i a
_ Jacket i a
_) = Int
s
size Leaf{}           = Int
1
size Jacket i a
Pure             = Int
0
{-# INLINE size #-}

-- | This is an internal function used to check from left-to-right if a 'Jacket' has any 'Leaf' nots or not.
nullLeft :: Jacket i a -> Bool
nullLeft :: Jacket i a -> Bool
nullLeft (Ap Int
_ Bool
nl Bool
_ Last i
_ Jacket i a
_ Jacket i a
_) = Bool
nl
nullLeft (Leaf i
_ a
_)        = Bool
False
nullLeft Jacket i a
Pure              = Bool
True
{-# INLINE nullLeft #-}

-- | This is an internal function used to check from right-to-left if a 'Jacket' has any 'Leaf' nots or not.
nullRight :: Jacket i a -> Bool
nullRight :: Jacket i a -> Bool
nullRight (Ap Int
_ Bool
_ Bool
nr Last i
_ Jacket i a
_ Jacket i a
_) = Bool
nr
nullRight (Leaf i
_ a
_)        = Bool
False
nullRight Jacket i a
Pure              = Bool
True
{-# INLINE nullRight #-}

-- | This is used to extract the maximal key from a 'Jacket'. This is used by 'moveTo' and 'moveToward' to
-- seek specific keys, borrowing the asympotic guarantees of the original structure in many cases!
maximal :: Jacket i a -> Last i
maximal :: Jacket i a -> Last i
maximal (Ap Int
_ Bool
_ Bool
_ Last i
li Jacket i a
_ Jacket i a
_) = Last i
li
maximal (Leaf i
i a
_)        = Maybe i -> Last i
forall a. Maybe a -> Last a
Last (i -> Maybe i
forall a. a -> Maybe a
Just i
i)
maximal Jacket i a
Pure              = Maybe i -> Last i
forall a. Maybe a -> Last a
Last Maybe i
forall a. Maybe a
Nothing
{-# INLINE maximal #-}

instance Functor (Jacket i) where
  fmap :: (a -> b) -> Jacket i a -> Jacket i b
fmap a -> b
f (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r) = Int
-> Bool -> Bool -> Last i -> Jacket i b -> Jacket i b -> Jacket i b
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
nl Bool
nr Last i
li ((a -> b) -> Jacket i a -> Jacket i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Jacket i a
l) ((a -> b) -> Jacket i a -> Jacket i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Jacket i a
r)
  fmap a -> b
f (Leaf i
i a
a)          = i -> b -> Jacket i b
forall i a. i -> a -> Jacket i a
Leaf i
i (a -> b
f a
a)
  fmap a -> b
_ Jacket i a
Pure                = Jacket i b
forall i a. Jacket i a
Pure
  {-# INLINE fmap #-}

instance Foldable (Jacket i) where
  foldMap :: (a -> m) -> Jacket i a -> m
foldMap a -> m
f (Ap Int
_ Bool
_ Bool
_ Last i
_ Jacket i a
l Jacket i a
r) = (a -> m) -> Jacket i a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f Jacket i a
l m -> m -> m
forall a. Monoid a => a -> a -> a
`mappend` (a -> m) -> Jacket i a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f Jacket i a
r
  foldMap a -> m
f (Leaf i
_ a
a)       = a -> m
f a
a
  foldMap a -> m
_ Jacket i a
Pure             = m
forall a. Monoid a => a
mempty
  {-# INLINE foldMap #-}

instance Traversable (Jacket i) where
  traverse :: (a -> f b) -> Jacket i a -> f (Jacket i b)
traverse a -> f b
f (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r) = Int
-> Bool -> Bool -> Last i -> Jacket i b -> Jacket i b -> Jacket i b
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
nl Bool
nr Last i
li (Jacket i b -> Jacket i b -> Jacket i b)
-> f (Jacket i b) -> f (Jacket i b -> Jacket i b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> Jacket i a -> f (Jacket i b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f Jacket i a
l f (Jacket i b -> Jacket i b) -> f (Jacket i b) -> f (Jacket i b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a -> f b) -> Jacket i a -> f (Jacket i b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f Jacket i a
r
  traverse a -> f b
f (Leaf i
i a
a)          = i -> b -> Jacket i b
forall i a. i -> a -> Jacket i a
Leaf i
i (b -> Jacket i b) -> f b -> f (Jacket i b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
a
  traverse a -> f b
_ Jacket i a
Pure                = Jacket i b -> f (Jacket i b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Jacket i b
forall i a. Jacket i a
Pure
  {-# INLINE traverse #-}

instance FunctorWithIndex i (Jacket i) where
  imap :: (i -> a -> b) -> Jacket i a -> Jacket i b
imap i -> a -> b
f = Jacket i a -> Jacket i b
go where
    go :: Jacket i a -> Jacket i b
go (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r) = Int
-> Bool -> Bool -> Last i -> Jacket i b -> Jacket i b -> Jacket i b
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
nl Bool
nr Last i
li (Jacket i a -> Jacket i b
go Jacket i a
l) (Jacket i a -> Jacket i b
go Jacket i a
r)
    go (Leaf i
i a
a)          = i -> b -> Jacket i b
forall i a. i -> a -> Jacket i a
Leaf i
i (i -> a -> b
f i
i a
a)
    go Jacket i a
Pure                = Jacket i b
forall i a. Jacket i a
Pure
  {-# INLINE imap #-}

instance FoldableWithIndex i (Jacket i) where
  ifoldMap :: (i -> a -> m) -> Jacket i a -> m
ifoldMap i -> a -> m
f = Jacket i a -> m
go where
    go :: Jacket i a -> m
go (Ap Int
_ Bool
_ Bool
_ Last i
_ Jacket i a
l Jacket i a
r) = Jacket i a -> m
go Jacket i a
l m -> m -> m
forall a. Monoid a => a -> a -> a
`mappend` Jacket i a -> m
go Jacket i a
r
    go (Leaf i
i a
a)       = i -> a -> m
f i
i a
a
    go Jacket i a
Pure             = m
forall a. Monoid a => a
mempty
  {-# INLINE ifoldMap #-}

instance TraversableWithIndex i (Jacket i) where
  itraverse :: (i -> a -> f b) -> Jacket i a -> f (Jacket i b)
itraverse i -> a -> f b
f = Jacket i a -> f (Jacket i b)
go where
    go :: Jacket i a -> f (Jacket i b)
go (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r) = Int
-> Bool -> Bool -> Last i -> Jacket i b -> Jacket i b -> Jacket i b
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
nl Bool
nr Last i
li (Jacket i b -> Jacket i b -> Jacket i b)
-> f (Jacket i b) -> f (Jacket i b -> Jacket i b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Jacket i a -> f (Jacket i b)
go Jacket i a
l f (Jacket i b -> Jacket i b) -> f (Jacket i b) -> f (Jacket i b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Jacket i a -> f (Jacket i b)
go Jacket i a
r
    go (Leaf i
i a
a)          = i -> b -> Jacket i b
forall i a. i -> a -> Jacket i a
Leaf i
i (b -> Jacket i b) -> f b -> f (Jacket i b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> i -> a -> f b
f i
i a
a
    go Jacket i a
Pure                = Jacket i b -> f (Jacket i b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Jacket i b
forall i a. Jacket i a
Pure
  {-# INLINE itraverse #-}

#if !MIN_VERSION_lens(5,0,0)
instance Lens.FunctorWithIndex     i (Jacket i) where imap = imap
instance Lens.FoldableWithIndex    i (Jacket i) where ifoldMap = ifoldMap
instance Lens.TraversableWithIndex i (Jacket i) where itraverse = itraverse
#endif

instance Semigroup (Jacket i a) where
  Jacket i a
l <> :: Jacket i a -> Jacket i a -> Jacket i a
<> Jacket i a
r = Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap (Jacket i a -> Int
forall i a. Jacket i a -> Int
size Jacket i a
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Jacket i a -> Int
forall i a. Jacket i a -> Int
size Jacket i a
r) (Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullLeft Jacket i a
l Bool -> Bool -> Bool
&& Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullLeft Jacket i a
r) (Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullRight Jacket i a
r Bool -> Bool -> Bool
&& Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullRight Jacket i a
l) (Jacket i a -> Last i
forall i a. Jacket i a -> Last i
maximal Jacket i a
l Last i -> Last i -> Last i
forall a. Semigroup a => a -> a -> a
<> Jacket i a -> Last i
forall i a. Jacket i a -> Last i
maximal Jacket i a
r) Jacket i a
l Jacket i a
r
  {-# INLINE (<>) #-}

-- | This is an illegal 'Monoid'.
instance Monoid (Jacket i a) where
  mempty :: Jacket i a
mempty = Jacket i a
forall i a. Jacket i a
Pure
  {-# INLINE mempty #-}

#if !(MIN_VERSION_base(4,11,0))
  mappend = (<>)
  {-# INLINE mappend #-}
#endif

-- | Construct a 'Jacket' from a 'Bazaar'
jacketIns :: Bazaar (Indexed i) a b t -> Jacket i a
jacketIns :: Bazaar (Indexed i) a b t -> Jacket i a
jacketIns (Bazaar forall (f :: * -> *). Applicative f => Indexed i a (f b) -> f t
bz) = Const (Jacket i a) t -> Jacket i a
forall a k (b :: k). Const a b -> a
getConst (Const (Jacket i a) t -> Jacket i a)
-> Const (Jacket i a) t -> Jacket i a
forall a b. (a -> b) -> a -> b
$ Indexed i a (Const (Jacket i a) b) -> Const (Jacket i a) t
forall (f :: * -> *). Applicative f => Indexed i a (f b) -> f t
bz (Indexed i a (Const (Jacket i a) b) -> Const (Jacket i a) t)
-> Indexed i a (Const (Jacket i a) b) -> Const (Jacket i a) t
forall a b. (a -> b) -> a -> b
$ (i -> a -> Const (Jacket i a) b)
-> Indexed i a (Const (Jacket i a) b)
forall i a b. (i -> a -> b) -> Indexed i a b
Indexed (\i
i -> Jacket i a -> Const (Jacket i a) b
forall k a (b :: k). a -> Const a b
Const (Jacket i a -> Const (Jacket i a) b)
-> (a -> Jacket i a) -> a -> Const (Jacket i a) b
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i)
{-# INLINE jacketIns #-}

------------------------------------------------------------------------------
-- * Flow
------------------------------------------------------------------------------

-- | Once we've updated a 'Zipper' we need to put the values back into the original
-- shape. 'Flow' is an illegal 'Applicative' that is used to put the values back.
newtype Flow i b a = Flow { Flow i b a -> Jacket i b -> a
runFlow :: Jacket i b -> a }

instance Functor (Flow i b) where
  fmap :: (a -> b) -> Flow i b a -> Flow i b b
fmap a -> b
f (Flow Jacket i b -> a
g) = (Jacket i b -> b) -> Flow i b b
forall i b a. (Jacket i b -> a) -> Flow i b a
Flow (a -> b
f (a -> b) -> (Jacket i b -> a) -> Jacket i b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Jacket i b -> a
g)
  {-# INLINE fmap #-}

instance Apply (Flow i b) where
  <.> :: Flow i b (a -> b) -> Flow i b a -> Flow i b b
(<.>) = Flow i b (a -> b) -> Flow i b a -> Flow i b b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>)
  {-# INLINE (<.>) #-}

-- | This is an illegal 'Applicative'.
instance Applicative (Flow i b) where
  pure :: a -> Flow i b a
pure a
a = (Jacket i b -> a) -> Flow i b a
forall i b a. (Jacket i b -> a) -> Flow i b a
Flow (a -> Jacket i b -> a
forall a b. a -> b -> a
const a
a)
  {-# INLINE pure #-}
  Flow Jacket i b -> a -> b
mf <*> :: Flow i b (a -> b) -> Flow i b a -> Flow i b b
<*> Flow Jacket i b -> a
ma = (Jacket i b -> b) -> Flow i b b
forall i b a. (Jacket i b -> a) -> Flow i b a
Flow ((Jacket i b -> b) -> Flow i b b)
-> (Jacket i b -> b) -> Flow i b b
forall a b. (a -> b) -> a -> b
$ \ Jacket i b
s -> case Jacket i b
s of
    Ap Int
_ Bool
_ Bool
_ Last i
_ Jacket i b
l Jacket i b
r -> Jacket i b -> a -> b
mf Jacket i b
l (Jacket i b -> a
ma Jacket i b
r)
    Jacket i b
_              -> Jacket i b -> a -> b
mf Jacket i b
s (Jacket i b -> a
ma Jacket i b
s)
  {-# INLINE (<*>) #-}

-- | Given a 'Bazaar' and a 'Jacket' build from that 'Bazaar' with 'jacketIns',
-- refill the 'Bazaar' with its new contents.
jacketOuts :: Bazaar (Indexed i) a b t -> Jacket j b -> t
jacketOuts :: Bazaar (Indexed i) a b t -> Jacket j b -> t
jacketOuts Bazaar (Indexed i) a b t
bz = Flow j b t -> Jacket j b -> t
forall i b a. Flow i b a -> Jacket i b -> a
runFlow (Flow j b t -> Jacket j b -> t) -> Flow j b t -> Jacket j b -> t
forall a b. (a -> b) -> a -> b
$ Bazaar (Indexed i) a b t
-> forall (f :: * -> *). Applicative f => Indexed i a (f b) -> f t
forall (p :: * -> * -> *) a b t.
Bazaar p a b t
-> forall (f :: * -> *). Applicative f => p a (f b) -> f t
runBazaar Bazaar (Indexed i) a b t
bz (Indexed i a (Flow j b b) -> Flow j b t)
-> Indexed i a (Flow j b b) -> Flow j b t
forall a b. (a -> b) -> a -> b
$ (i -> a -> Flow j b b) -> Indexed i a (Flow j b b)
forall i a b. (i -> a -> b) -> Indexed i a b
Indexed ((i -> a -> Flow j b b) -> Indexed i a (Flow j b b))
-> (i -> a -> Flow j b b) -> Indexed i a (Flow j b b)
forall a b. (a -> b) -> a -> b
$ \ i
_ a
_ -> (Jacket j b -> b) -> Flow j b b
forall i b a. (Jacket i b -> a) -> Flow i b a
Flow ((Jacket j b -> b) -> Flow j b b)
-> (Jacket j b -> b) -> Flow j b b
forall a b. (a -> b) -> a -> b
$ \ Jacket j b
t -> case Jacket j b
t of
  Leaf j
_ b
a -> b
a
  Jacket j b
_        -> String -> b
forall a. HasCallStack => String -> a
error String
"jacketOuts: wrong shape"
{-# INLINE jacketOuts #-}

-- | This is only a valid 'Lens' if you don't change the shape of the 'Jacket'!
jacket :: AnIndexedTraversal i s t a b -> Lens s t (Jacket i a) (Jacket j b)
jacket :: AnIndexedTraversal i s t a b -> Lens s t (Jacket i a) (Jacket j b)
jacket AnIndexedTraversal i s t a b
l Jacket i a -> f (Jacket j b)
f s
s = Bazaar (Indexed i) a b t -> Jacket j b -> t
forall i a b t j. Bazaar (Indexed i) a b t -> Jacket j b -> t
jacketOuts Bazaar (Indexed i) a b t
bz (Jacket j b -> t) -> f (Jacket j b) -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Jacket i a -> f (Jacket j b)
f (Bazaar (Indexed i) a b t -> Jacket i a
forall i a b t. Bazaar (Indexed i) a b t -> Jacket i a
jacketIns Bazaar (Indexed i) a b t
bz) where
  bz :: Bazaar (Indexed i) a b t
bz = AnIndexedTraversal i s t a b
l Indexed i a (Bazaar (Indexed i) a b b)
forall (p :: * -> * -> *) (w :: * -> * -> * -> *) a b.
Sellable p w =>
p a (w a b b)
sell s
s
{-# INLINE jacket #-}

------------------------------------------------------------------------------
-- * Paths
------------------------------------------------------------------------------

-- | A 'Path' into a 'Jacket' that ends at a 'Leaf'.
data Path i a
  = ApL Int Bool Bool (Last i) !(Path i a) !(Jacket i a)
  | ApR Int Bool Bool (Last i) !(Jacket i a) !(Path i a)
  | Start
  deriving Int -> Path i a -> ShowS
[Path i a] -> ShowS
Path i a -> String
(Int -> Path i a -> ShowS)
-> (Path i a -> String) -> ([Path i a] -> ShowS) -> Show (Path i a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall i a. (Show i, Show a) => Int -> Path i a -> ShowS
forall i a. (Show i, Show a) => [Path i a] -> ShowS
forall i a. (Show i, Show a) => Path i a -> String
showList :: [Path i a] -> ShowS
$cshowList :: forall i a. (Show i, Show a) => [Path i a] -> ShowS
show :: Path i a -> String
$cshow :: forall i a. (Show i, Show a) => Path i a -> String
showsPrec :: Int -> Path i a -> ShowS
$cshowsPrec :: forall i a. (Show i, Show a) => Int -> Path i a -> ShowS
Show

instance Functor (Path i) where
  fmap :: (a -> b) -> Path i a -> Path i b
fmap a -> b
f (ApL Int
m Bool
nl Bool
nr Last i
li Path i a
p Jacket i a
q) = Int -> Bool -> Bool -> Last i -> Path i b -> Jacket i b -> Path i b
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li ((a -> b) -> Path i a -> Path i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Path i a
p) ((a -> b) -> Jacket i a -> Jacket i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Jacket i a
q)
  fmap a -> b
f (ApR Int
m Bool
nl Bool
nr Last i
li Jacket i a
p Path i a
q) = Int -> Bool -> Bool -> Last i -> Jacket i b -> Path i b -> Path i b
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
nl Bool
nr Last i
li ((a -> b) -> Jacket i a -> Jacket i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Jacket i a
p) ((a -> b) -> Path i a -> Path i b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Path i a
q)
  fmap a -> b
_ Path i a
Start = Path i b
forall i a. Path i a
Start
  {-# INLINE fmap #-}

-- | Calculate the absolute position of the 'Leaf' targeted by a 'Path'.
--
-- This can be quite expensive for right-biased traversals such as you
-- receive from a list.
offset :: Path i a -> Int
offset :: Path i a -> Int
offset Path i a
Start           = Int
0
offset (ApL Int
_ Bool
_ Bool
_ Last i
_ Path i a
q Jacket i a
_) = Path i a -> Int
forall i a. Path i a -> Int
offset Path i a
q
offset (ApR Int
_ Bool
_ Bool
_ Last i
_ Jacket i a
l Path i a
q) = Jacket i a -> Int
forall i a. Jacket i a -> Int
size Jacket i a
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Path i a -> Int
forall i a. Path i a -> Int
offset Path i a
q
{-# INLINE offset #-}

-- | Return the total number of children in the 'Jacket' by walking the
-- 'Path' to the root.
pathsize :: Path i a -> Int
pathsize :: Path i a -> Int
pathsize = Int -> Path i a -> Int
forall i a. Int -> Path i a -> Int
go Int
1 where
  go :: Int -> Path i a -> Int
go Int
n Path i a
Start = Int
n
  go Int
_ (ApL Int
n Bool
_ Bool
_ Last i
_ Path i a
p Jacket i a
_) = Int -> Path i a -> Int
go Int
n Path i a
p
  go Int
_ (ApR Int
n Bool
_ Bool
_ Last i
_ Jacket i a
_ Path i a
p) = Int -> Path i a -> Int
go Int
n Path i a
p
{-# INLINE pathsize #-}

-- * Recursion
--
-- For several operations, we unroll the first step of the recursion (or part
-- of it) so GHC can inline better. There are two specific cases that we care
-- about: The "lens case", where the entire tree is just (Leaf (Identity x)), and the
-- "list case", where the traversal tree is right-biased, as in (Ap (Leaf (Identity x))
-- (Ap (Leaf (Identity y)) ...)). It should be safe to delete any of these cases.

-- | Reconstruct a 'Jacket' from a 'Path'.
recompress :: Path i a -> i -> a -> Jacket i a
recompress :: Path i a -> i -> a -> Jacket i a
recompress Path i a
Start i
i a
a = i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i a
a -- Unrolled: The lens case.
recompress (ApL Int
m Bool
_ Bool
_ Last i
li Path i a
Start Jacket i a
r) i
i a
a = Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li (i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i a
a) Jacket i a
r -- Unrolled: The list case. In particular, a right-biased tree that we haven't moved rightward in.
recompress Path i a
p i
i a
a = Path i a -> Jacket i a -> Jacket i a
forall i a. Path i a -> Jacket i a -> Jacket i a
go Path i a
p (i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i a
a) where
  go :: Path i a -> Jacket i a -> Jacket i a
go Path i a
Start              Jacket i a
q = Jacket i a
q
  go (ApL Int
m Bool
_ Bool
_ Last i
li Path i a
q Jacket i a
r) Jacket i a
l = Path i a -> Jacket i a -> Jacket i a
go Path i a
q (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
l Jacket i a
r)
  go (ApR Int
m Bool
_ Bool
_ Last i
li Jacket i a
l Path i a
q) Jacket i a
r = Path i a -> Jacket i a -> Jacket i a
go Path i a
q (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
l Jacket i a
r)
{-# INLINE recompress #-}

-- | Walk down the tree to the leftmost child.
startl :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl Path i a
p0 (Leaf i
i a
a) r
_ Path i a -> i -> a -> r
kp = Path i a -> i -> a -> r
kp Path i a
p0 i
i a
a -- Unrolled: The lens case.
startl Path i a
p0 (Ap Int
m Bool
nl Bool
nr Last i
li (Leaf i
i a
a) Jacket i a
r) r
_ Path i a -> i -> a -> r
kp = Path i a -> i -> a -> r
kp (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li Path i a
p0 Jacket i a
r) i
i a
a -- Unrolled: The list case. (Is this one a good idea?)
startl Path i a
p0 Jacket i a
c0 r
kn Path i a -> i -> a -> r
kp = Path i a -> Jacket i a -> r
go Path i a
p0 Jacket i a
c0 where
  go :: Path i a -> Jacket i a -> r
go Path i a
p (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r)
    | Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullLeft Jacket i a
l  = Path i a -> Jacket i a -> r
go (Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
nl Bool
nr Last i
li Jacket i a
forall i a. Jacket i a
Pure Path i a
p) Jacket i a
r
    | Bool
otherwise   = Path i a -> Jacket i a -> r
go (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li Path i a
p Jacket i a
r) Jacket i a
l
  go Path i a
p (Leaf i
i a
a) = Path i a -> i -> a -> r
kp Path i a
p i
i a
a
  go Path i a
_ Jacket i a
Pure       = r
kn
{-# INLINE startl #-}

-- | Walk down the tree to the rightmost child.
startr :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startr :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startr Path i a
p0 (Leaf i
i a
a) r
_ Path i a -> i -> a -> r
kp = Path i a -> i -> a -> r
kp Path i a
p0 i
i a
a -- Unrolled: The lens case.
startr Path i a
p0 Jacket i a
c0 r
kn Path i a -> i -> a -> r
kp = Path i a -> Jacket i a -> r
go Path i a
p0 Jacket i a
c0 where
  go :: Path i a -> Jacket i a -> r
go Path i a
p (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r)
     | Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullRight Jacket i a
r = Path i a -> Jacket i a -> r
go (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li Path i a
p Jacket i a
forall i a. Jacket i a
Pure) Jacket i a
l
     | Bool
otherwise   = Path i a -> Jacket i a -> r
go (Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Path i a
p) Jacket i a
r
  go Path i a
p (Leaf i
i a
a)  = Path i a -> i -> a -> r
kp Path i a
p i
i a
a
  go Path i a
_ Jacket i a
Pure        = r
kn
{-# INLINE startr #-}

-- | Move left one 'Leaf'.
movel :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
movel :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
movel Path i a
p0 Jacket i a
c0 r
kn Path i a -> i -> a -> r
kp = Path i a -> Jacket i a -> r
go Path i a
p0 Jacket i a
c0 where
  go :: Path i a -> Jacket i a -> r
go Path i a
Start Jacket i a
_ = r
kn
  go (ApR Int
m Bool
_ Bool
_ Last i
li Jacket i a
l Path i a
q) Jacket i a
r
    | Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullRight Jacket i a
l = Path i a -> Jacket i a -> r
go Path i a
q (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
forall i a. Jacket i a
Pure Jacket i a
r)
    | Bool
otherwise   = Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startr (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
False Bool
False Last i
li Path i a
q Jacket i a
r) Jacket i a
l r
kn Path i a -> i -> a -> r
kp
  go (ApL Int
m Bool
_ Bool
_ Last i
li Path i a
p Jacket i a
r) Jacket i a
l = Path i a -> Jacket i a -> r
go Path i a
p (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
l Jacket i a
r)
{-# INLINE movel #-}

-- | Move right one 'Leaf'.
mover :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
mover :: Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
mover Path i a
p0 Jacket i a
c0 r
kn Path i a -> i -> a -> r
kp = Path i a -> Jacket i a -> r
go Path i a
p0 Jacket i a
c0 where
  go :: Path i a -> Jacket i a -> r
go Path i a
Start Jacket i a
_ = r
kn
  go (ApL Int
m Bool
_ Bool
_ Last i
li Path i a
q Jacket i a
r) Jacket i a
l
    | Jacket i a -> Bool
forall i a. Jacket i a -> Bool
nullLeft Jacket i a
r  = Path i a -> Jacket i a -> r
go Path i a
q (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
l Jacket i a
forall i a. Jacket i a
Pure)
    | Bool
otherwise   = Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl (Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
False Bool
False Last i
li Jacket i a
l Path i a
q) Jacket i a
r r
kn Path i a -> i -> a -> r
kp
  go (ApR Int
m Bool
_ Bool
_ Last i
li Jacket i a
l Path i a
p) Jacket i a
r = Path i a -> Jacket i a -> r
go Path i a
p (Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
forall i a.
Int
-> Bool -> Bool -> Last i -> Jacket i a -> Jacket i a -> Jacket i a
Ap Int
m Bool
False Bool
False Last i
li Jacket i a
l Jacket i a
r)
{-# INLINE mover #-}

-----------------------------------------------------------------------------
-- * Zippers
-----------------------------------------------------------------------------

-- | This is used to represent the 'Top' of the 'Zipper'.
--
-- Every 'Zipper' starts with 'Top'.
--
-- /e.g./ @'Top' ':>>' a@ is the type of the trivial 'Zipper'.
data Top

-- | This is the type of a 'Zipper'. It visually resembles a \"breadcrumb trail\" as
-- used in website navigation. Each breadcrumb in the trail represents a level you
-- can move up to.
--
-- This type operator associates to the left, so you can use a type like
--
-- @'Top' ':>>' ('String','Double') ':>>' 'String' ':>>' 'Char'@
--
-- to represent a 'Zipper' from @('String','Double')@ down to 'Char' that has an intermediate
-- crumb for the 'String' containing the 'Char'.
--
-- You can construct a 'Zipper' into *any* data structure with 'zipper'.
--
-- You can repackage up the contents of a 'Zipper' with 'rezip'.
--
-- >>> rezip $ zipper 42
-- 42
--
-- The combinators in this module provide lot of things you can do to the
-- 'Zipper' while you have it open.
--
-- Note that a value of type @h ':>' s ':>' a@ doesn't actually contain a value
-- of type @h ':>' s@ -- as we descend into a level, the previous level is
-- unpacked and stored in 'Coil' form. Only one value of type @_ ':>' _@ exists
-- at any particular time for any particular 'Zipper'.

data Zipper h i a = Ord i => Zipper !(Coil h i a) Int !Int !(Path i a) i a

-- Top :>> Map String Int :> Int :@ String :>> Bool

infixr 9 :@
-- | An empty data type, used to represent the pairing of a position in
-- a 'Zipper' with an index. See ':>'.
data (:@) a i

infixl 8 :>
-- | This type family represents a 'Zipper' with the @p@ variable
-- abstracting over the position and the index, in terms of ':@'. You
-- can visually see it in type signatures as:
--
-- @
-- h ':>' (a ':@' i) = 'Zipper' h i a
-- @
--
type family (:>) h p
type instance h :> (a :@ i) = Zipper h i a

infixl 8 :>>
-- | Many zippers are indexed by Int keys. This type alias is convenient for reducing syntactic noise for talking about these boring indices.
type h :>> a = Zipper h Int a

-- | This represents the type a 'Zipper' will have when it is fully 'Zipped' back up.
type family Zipped h a
type instance Zipped Top a            = a
type instance Zipped (Zipper h i a) s = Zipped h a

-- | A 'Coil' is a linked list of the levels above the current one. The length
-- of a 'Coil' is known at compile time.
--
-- This is part of the internal structure of a 'Zipper'. You shouldn't need to manipulate this directly.
#ifndef HLINT
data Coil t i a where
  Coil :: Coil Top Int a
  Snoc :: Ord i => !(Coil h j s) -> AnIndexedTraversal' i s a -> Int -> !Int -> !(Path j s) -> j -> (Jacket i a -> s) -> Coil (Zipper h j s) i a
#endif

-- | This 'Lens' views the current target of the 'Zipper'.
focus :: IndexedLens' i (Zipper h i a) a
focus :: p a (f a) -> Zipper h i a -> f (Zipper h i a)
focus p a (f a)
f (Zipper Coil h i a
h Int
t Int
o Path i a
p i
i a
a) = Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h i a
h Int
t Int
o Path i a
p i
i (a -> Zipper h i a) -> f a -> f (Zipper h i a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p a (f a) -> i -> a -> f a
forall i (p :: * -> * -> *) a b.
Indexable i p =>
p a b -> i -> a -> b
indexed p a (f a)
f i
i a
a
{-# INLINE focus #-}

-- | Construct a 'Zipper' that can explore anything, and start it at the 'Top'.
zipper :: a -> Top :>> a
zipper :: a -> Top :>> a
zipper = Coil Top Int a -> Int -> Int -> Path Int a -> Int -> a -> Top :>> a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil Top Int a
forall a. Coil Top Int a
Coil Int
0 Int
0 Path Int a
forall i a. Path i a
Start Int
0
{-# INLINE zipper #-}

-- | Return the index of the focus.
focalPoint :: Zipper h i a -> i
focalPoint :: Zipper h i a -> i
focalPoint (Zipper Coil h i a
_ Int
_ Int
_ Path i a
_ i
i a
_) = i
i
{-# INLINE focalPoint #-}

-- | Return the index into the current 'Traversal' within the current level of the 'Zipper'.
--
-- @'jerkTo' ('tooth' l) l = 'Just'@
--
-- Mnemonically, zippers have a number of 'teeth' within each level. This is which 'tooth' you are currently at.
--
-- This is based on ordinal position regardless of the underlying index type. It may be excessively expensive for a list.
--
-- 'focalPoint' may be much cheaper if you have a 'Traversal' indexed by ordinal position!
tooth :: Zipper h i a -> Int
tooth :: Zipper h i a -> Int
tooth (Zipper Coil h i a
_ Int
t Int
o Path i a
_ i
_ a
_) = Int
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
o
{-# INLINE tooth #-}

-- | Move the 'Zipper' 'upward', closing the current level and focusing on the parent element.
--
-- NB: Attempts to move upward from the 'Top' of the 'Zipper' will fail to typecheck.
--
upward :: Ord j => h :> s:@j :> a:@i -> h :> s:@j
upward :: ((h :> (s :@ j)) :> (a :@ i)) -> h :> (s :@ j)
upward (Zipper (Snoc h _ t o p j k) _ _ q i x) = Coil h j s -> Int -> Int -> Path j s -> j -> s -> Zipper h j s
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h j s
h Int
t Int
o Path j s
p j
j (s -> Zipper h j s) -> s -> Zipper h j s
forall a b. (a -> b) -> a -> b
$ Jacket i a -> s
k (Jacket i a -> s) -> Jacket i a -> s
forall a b. (a -> b) -> a -> b
$ Path i a -> i -> a -> Jacket i a
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path i a
q i
i a
x
{-# INLINE upward #-}

-- | Jerk the 'Zipper' one 'tooth' to the 'rightward' within the current 'Lens' or 'Traversal'.
--
-- Attempts to move past the start of the current 'Traversal' (or trivially, the current 'Lens')
-- will return 'mzero'.
--
-- >>> isNothing $ zipper "hello" & rightward
-- True
--
-- >>> zipper "hello" & fromWithin traverse & rightward <&> view focus
-- 'e'
--
-- >>> zipper "hello" & fromWithin traverse & rightward <&> focus .~ 'u' <&> rezip
-- "hullo"
--
-- >>> rezip $ zipper (1,2) & fromWithin both & tug rightward & focus .~ 3
-- (1,3)
rightward :: MonadPlus m => h :> a:@i -> m (h :> a:@i)
rightward :: (h :> (a :@ i)) -> m (h :> (a :@ i))
rightward (Zipper h t o p i a) = Path i a
-> Jacket i a
-> m (Zipper h i a)
-> (Path i a -> i -> a -> m (Zipper h i a))
-> m (Zipper h i a)
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
mover Path i a
p (i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i a
a) m (Zipper h i a)
forall (m :: * -> *) a. MonadPlus m => m a
mzero ((Path i a -> i -> a -> m (Zipper h i a)) -> m (Zipper h i a))
-> (Path i a -> i -> a -> m (Zipper h i a)) -> m (Zipper h i a)
forall a b. (a -> b) -> a -> b
$ \Path i a
q i
j a
b -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Zipper h i a -> m (Zipper h i a))
-> Zipper h i a -> m (Zipper h i a)
forall a b. (a -> b) -> a -> b
$ Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h i a
h Int
t (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Path i a
q i
j a
b
{-# INLINE rightward #-}

-- | Jerk the 'Zipper' 'leftward' one 'tooth' within the current 'Lens' or 'Traversal'.
--
-- Attempts to move past the end of the current 'Traversal' (or trivially, the current 'Lens')
-- will return 'mzero'.
--
-- >>> isNothing $ zipper "hello" & leftward
-- True

-- >>> isNothing $ zipper "hello" & within traverse >>= leftward
-- True
--
-- >>> zipper "hello" & within traverse <&> tug leftward
-- Just 'h'
--
-- >>> zipper "hello" & fromWithin traverse & tug rightward & tug leftward & view focus
-- 'h'
leftward :: MonadPlus m => h :> a:@i -> m (h :> a:@i)
leftward :: (h :> (a :@ i)) -> m (h :> (a :@ i))
leftward (Zipper h t o p i a) = Path i a
-> Jacket i a
-> m (Zipper h i a)
-> (Path i a -> i -> a -> m (Zipper h i a))
-> m (Zipper h i a)
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
movel Path i a
p (i -> a -> Jacket i a
forall i a. i -> a -> Jacket i a
Leaf i
i a
a) m (Zipper h i a)
forall (m :: * -> *) a. MonadPlus m => m a
mzero ((Path i a -> i -> a -> m (Zipper h i a)) -> m (Zipper h i a))
-> (Path i a -> i -> a -> m (Zipper h i a)) -> m (Zipper h i a)
forall a b. (a -> b) -> a -> b
$ \Path i a
q i
j a
b -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Zipper h i a -> m (Zipper h i a))
-> Zipper h i a -> m (Zipper h i a)
forall a b. (a -> b) -> a -> b
$ Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h i a
h Int
t (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Path i a
q i
j a
b
{-# INLINE leftward #-}

-- | Move to the leftmost position of the current 'Traversal'.
--
-- This is just a convenient alias for @'farthest' 'leftward'@.
--
-- >>> zipper "hello" & fromWithin traverse & leftmost & focus .~ 'a' & rezip
-- "aello"
leftmost :: a :> b:@i -> a :> b:@i
leftmost :: (a :> (b :@ i)) -> a :> (b :@ i)
leftmost (Zipper h _ _ p i a) = Path i b
-> Jacket i b
-> Zipper a i b
-> (Path i b -> i -> b -> Zipper a i b)
-> Zipper a i b
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl Path i b
forall i a. Path i a
Start (Path i b -> i -> b -> Jacket i b
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path i b
p i
i b
a) (String -> Zipper a i b
forall a. HasCallStack => String -> a
error String
"leftmost: bad Jacket structure") (Coil a i b -> Int -> Int -> Path i b -> i -> b -> Zipper a i b
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil a i b
h Int
0 Int
0)
{-# INLINE leftmost #-}

-- | Move to the rightmost position of the current 'Traversal'.
--
-- This is just a convenient alias for @'farthest' 'rightward'@.
--
-- >>> zipper "hello" & fromWithin traverse & rightmost & focus .~ 'y' & leftmost & focus .~ 'j' & rezip
-- "jelly"
rightmost :: a :> b:@i -> a :> b:@i
rightmost :: (a :> (b :@ i)) -> a :> (b :@ i)
rightmost (Zipper h _ _ p i a) = Path i b
-> Jacket i b
-> Zipper a i b
-> (Path i b -> i -> b -> Zipper a i b)
-> Zipper a i b
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startr Path i b
forall i a. Path i a
Start (Path i b -> i -> b -> Jacket i b
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path i b
p i
i b
a) (String -> Zipper a i b
forall a. HasCallStack => String -> a
error String
"rightmost: bad Jacket structure") (\Path i b
q -> Coil a i b -> Int -> Int -> Path i b -> i -> b -> Zipper a i b
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil a i b
h (Path i b -> Int
forall i a. Path i a -> Int
offset Path i b
q) Int
0 Path i b
q)
{-# INLINE rightmost #-}

-- | This allows you to safely 'tug' 'leftward' or 'tug' 'rightward' on a
-- 'Zipper'. This will attempt the move, and stay where it was if it fails.
--
-- The more general signature allows its use in other circumstances, however.
--
-- @'tug' f x ≡ 'fromMaybe' a (f a)@
--
-- >>> fmap rezip $ zipper "hello" & within traverse <&> tug leftward <&> focus .~ 'j'
-- "jello"
--
-- >>> fmap rezip $ zipper "hello" & within traverse <&> tug rightward <&> focus .~ 'u'
-- "hullo"
tug :: (a -> Maybe a) -> a -> a
tug :: (a -> Maybe a) -> a -> a
tug a -> Maybe a
f a
a = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
a (a -> Maybe a
f a
a)
{-# INLINE tug #-}

-- | This allows you to safely @'tug' 'leftward'@ or @'tug' 'rightward'@
-- multiple times on a 'Zipper', moving multiple steps in a given direction
-- and stopping at the last place you couldn't move from. This lets you safely
-- move a 'Zipper', because it will stop at either end.
--
-- >>> fmap rezip $ zipper "stale" & within traverse <&> tugs rightward 2 <&> focus .~ 'y'
-- "style"
--
-- >>> rezip $ zipper "want" & fromWithin traverse & tugs rightward 2 & focus .~ 'r' & tugs leftward 100 & focus .~ 'c'
-- "cart"
tugs :: (a -> Maybe a) -> Int -> a -> a
tugs :: (a -> Maybe a) -> Int -> a -> a
tugs a -> Maybe a
f Int
n0
  | Int
n0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0    = String -> a -> a
forall a. HasCallStack => String -> a
error String
"tugs: negative tug count"
  | Bool
otherwise = Int -> a -> a
go Int
n0
  where
    go :: Int -> a -> a
go Int
0 a
a = a
a
    go Int
n a
a = a -> (a -> a) -> Maybe a -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
a (Int -> a -> a
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) (a -> Maybe a
f a
a)
{-# INLINE tugs #-}

-- | Move in a direction as far as you can go, then stop there.
--
-- This repeatedly applies a function until it returns 'Nothing', and then returns the last answer.
--
-- >>> fmap rezip $ zipper ("hello","world") & downward _1 & within traverse <&> rightmost <&> focus .~ 'a'
-- ("hella","world")
--
-- >>> rezip $ zipper ("hello","there") & fromWithin (both.traverse) & rightmost & focus .~ 'm'
-- ("hello","therm")
farthest :: (a -> Maybe a) -> a -> a
farthest :: (a -> Maybe a) -> a -> a
farthest a -> Maybe a
f = a -> a
go where
  go :: a -> a
go a
a = a -> (a -> a) -> Maybe a -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
a a -> a
go (a -> Maybe a
f a
a)
{-# INLINE farthest #-}

-- | This allows for you to repeatedly pull a 'Zipper' in a given direction, failing if it falls off the end.
--
-- >>> isNothing $ zipper "hello" & within traverse >>= jerks rightward 10
-- True
--
-- >>> fmap rezip $ zipper "silly" & within traverse >>= jerks rightward 3 <&> focus .~ 'k'
-- "silky"
jerks :: Fail.MonadFail m => (a -> m a) -> Int -> a -> m a
jerks :: (a -> m a) -> Int -> a -> m a
jerks a -> m a
f Int
n0
  | Int
n0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0    = \a
_ -> String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"jerks: negative jerk count"
  | Bool
otherwise = Int -> a -> m a
go Int
n0
  where
    go :: Int -> a -> m a
go Int
0 a
a = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
    go Int
n a
a = a -> m a
f a
a m a -> (a -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> a -> m a
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
{-# INLINE jerks #-}

-- | 'jerksError' is Like 'jerks', but it uses 'error' instead of 'fail' when
-- the supplied 'Int' is negative. This allows 'jerksError' to have a 'Monad'
-- constraint instead of the less general 'MonadFail'.
jerksError :: Monad m => (a -> m a) -> Int -> a -> m a
jerksError :: (a -> m a) -> Int -> a -> m a
jerksError a -> m a
f Int
n0
  | Int
n0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0    = \a
_ -> String -> m a
forall a. HasCallStack => String -> a
error String
"jerksError: negative jerk count"
  | Bool
otherwise = Int -> a -> m a
go Int
n0
  where
    go :: Int -> a -> m a
go Int
0 a
a = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
    go Int
n a
a = a -> m a
f a
a m a -> (a -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> a -> m a
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
{-# INLINE jerksError #-}

-- | Returns the number of siblings at the current level in the 'Zipper'.
--
-- @'teeth' z '>=' 1@
--
-- /NB:/ If the current 'Traversal' targets an infinite number of elements then this may not terminate.
--
-- This is also a particularly expensive operation to perform on an unbalanced tree.
--
-- >>> zipper ("hello","world") & teeth
-- 1
--
-- >>> zipper ("hello","world") & fromWithin both & teeth
-- 2
--
-- >>> zipper ("hello","world") & downward _1 & teeth
-- 1
--
-- >>> zipper ("hello","world") & downward _1 & fromWithin traverse & teeth
-- 5
--
-- >>> zipper ("hello","world") & fromWithin (_1.traverse) & teeth
-- 5
--
-- >>> zipper ("hello","world") & fromWithin (both.traverse) & teeth
-- 10
teeth :: h :> a:@i -> Int
teeth :: (h :> (a :@ i)) -> Int
teeth (Zipper _ _ _ p _ _) = Path i a -> Int
forall i a. Path i a -> Int
pathsize Path i a
p
{-# INLINE teeth #-}

-- | Move the 'Zipper' horizontally to the element in the @n@th position in the
-- current level, absolutely indexed, starting with the 'farthest' 'leftward' as @0@.
--
-- This returns 'mzero' if the target element doesn't exist.
--
-- @'jerkTo' n ≡ 'jerks' 'rightward' n '.' 'farthest' 'leftward'@
--
-- >>> isNothing $ zipper "not working." & jerkTo 20
-- True

-- >>> isNothing $ zipper "not working." & fromWithin traverse & jerkTo 20
-- True
--
-- >>> fmap rezip $ zipper "not working" & within traverse >>= jerkTo 2 <&> focus .~ 'w'
-- Just "now working"
jerkTo :: MonadPlus m => Int -> (h :> a:@i) -> m (h :> a:@i)
jerkTo :: Int -> (h :> (a :@ i)) -> m (h :> (a :@ i))
jerkTo Int
n h :> (a :@ i)
z = case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
k Int
n of
  -- We use jerksError here instead of jerks to avoid incurring a useless
  -- MonadFail constraint (as we ensure that jerksError is never called with
  -- a negative Int argument).
  Ordering
LT -> (Zipper h i a -> m (Zipper h i a))
-> Int -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => (a -> m a) -> Int -> a -> m a
jerksError Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) h a i.
MonadPlus m =>
(h :> (a :@ i)) -> m (h :> (a :@ i))
rightward (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) h :> (a :@ i)
Zipper h i a
z
  Ordering
EQ -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => a -> m a
return h :> (a :@ i)
Zipper h i a
z
  Ordering
GT -> (Zipper h i a -> m (Zipper h i a))
-> Int -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => (a -> m a) -> Int -> a -> m a
jerksError Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) h a i.
MonadPlus m =>
(h :> (a :@ i)) -> m (h :> (a :@ i))
leftward (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) h :> (a :@ i)
Zipper h i a
z
  where k :: Int
k = Zipper h i a -> Int
forall h i a. Zipper h i a -> Int
tooth h :> (a :@ i)
Zipper h i a
z
{-# INLINE jerkTo #-}

-- | Move the 'Zipper' horizontally to the element in the @n@th position of the
-- current level, absolutely indexed, starting with the 'farthest' 'leftward' as @0@.
--
-- If the element at that position doesn't exist, then this will clamp to the range @0 '<=' n '<' 'teeth'@.
--
-- @'tugTo' n ≡ 'tugs' 'rightward' n '.' 'farthest' 'leftward'@
--
-- >>> rezip $ zipper "not working." & fromWithin traverse & tugTo 100 & focus .~ '!' & tugTo 1 & focus .~ 'u'
-- "nut working!"
tugTo :: Int -> h :> a:@i -> h :> a:@i
tugTo :: Int -> (h :> (a :@ i)) -> h :> (a :@ i)
tugTo Int
n h :> (a :@ i)
z = case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
k Int
n of
  Ordering
LT -> (Zipper h i a -> Maybe (Zipper h i a))
-> Int -> Zipper h i a -> Zipper h i a
forall a. (a -> Maybe a) -> Int -> a -> a
tugs Zipper h i a -> Maybe (Zipper h i a)
forall (m :: * -> *) h a i.
MonadPlus m =>
(h :> (a :@ i)) -> m (h :> (a :@ i))
rightward (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) h :> (a :@ i)
Zipper h i a
z
  Ordering
EQ -> h :> (a :@ i)
z
  Ordering
GT -> (Zipper h i a -> Maybe (Zipper h i a))
-> Int -> Zipper h i a -> Zipper h i a
forall a. (a -> Maybe a) -> Int -> a -> a
tugs Zipper h i a -> Maybe (Zipper h i a)
forall (m :: * -> *) h a i.
MonadPlus m =>
(h :> (a :@ i)) -> m (h :> (a :@ i))
leftward (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) h :> (a :@ i)
Zipper h i a
z
  where k :: Int
k = Zipper h i a -> Int
forall h i a. Zipper h i a -> Int
tooth h :> (a :@ i)
Zipper h i a
z
{-# INLINE tugTo #-}

-- | Move towards a particular index in the current 'Traversal'.
moveToward :: i -> h :> a:@i -> h :> a:@i
moveToward :: i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward i
i z :: h :> (a :@ i)
z@(Zipper h _ _ p0 j s0)
  | i
i i -> i -> Bool
forall a. Eq a => a -> a -> Bool
== i
j   = h :> (a :@ i)
z
  | Bool
otherwise = Path i a -> Jacket i a -> Zipper h i a
go Path i a
forall i a. Path i a
Start (Path i a -> i -> a -> Jacket i a
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path i a
p0 i
j a
s0)
  where
    go :: Path i a -> Jacket i a -> Zipper h i a
go Path i a
_ Jacket i a
Pure = h :> (a :@ i)
Zipper h i a
z
    go Path i a
p (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r)
      | Last (Just i
k) <- Jacket i a -> Last i
forall i a. Jacket i a -> Last i
maximal Jacket i a
l, i
k i -> i -> Bool
forall a. Ord a => a -> a -> Bool
>= i
i = Path i a -> Jacket i a -> Zipper h i a
go (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li Path i a
p Jacket i a
r) Jacket i a
l
      | Bool
otherwise      = Path i a -> Jacket i a -> Zipper h i a
go (Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Path i a
p) Jacket i a
r
    go Path i a
p (Leaf i
k a
a) = Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h i a
h (Path i a -> Int
forall i a. Path i a -> Int
offset Path i a
p) Int
0 Path i a
p i
k a
a
{-# INLINE moveToward #-}

-- | Move horizontally to a particular index @i@ in the current
-- 'Traversal'. In the case of simple zippers, the index is 'Int' and
-- we can move between traversals fairly easily:
--
-- >>> zipper (42, 32) & fromWithin both & moveTo 0 <&> view focus
-- 42
--
-- >>> zipper (42, 32) & fromWithin both & moveTo 1 <&> view focus
-- 32
--
moveTo :: MonadPlus m => i -> h :> a:@i -> m (h :> a:@i)
moveTo :: i -> (h :> (a :@ i)) -> m (h :> (a :@ i))
moveTo i
i h :> (a :@ i)
z = case i -> (h :> (a :@ i)) -> h :> (a :@ i)
forall i h a. i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward i
i h :> (a :@ i)
z of
  z' :: h :> (a :@ i)
z'@(Zipper _ _ _ _ j _)
    | i
i i -> i -> Bool
forall a. Eq a => a -> a -> Bool
== i
j    -> Zipper h i a -> m (Zipper h i a)
forall (m :: * -> *) a. Monad m => a -> m a
return h :> (a :@ i)
Zipper h i a
z'
    | Bool
otherwise -> m (h :> (a :@ i))
forall (m :: * -> *) a. MonadPlus m => m a
mzero
{-# INLINE moveTo #-}

-- | Construct an 'IndexedLens' from 'ALens' where the index is fixed to @0@.
lensed :: ALens' s a -> IndexedLens' Int s a
lensed :: ALens' s a -> IndexedLens' Int s a
lensed ALens' s a
l p a (f a)
f = ALens' s a -> (a -> f a) -> s -> f s
forall s t a b. ALens s t a b -> Lens s t a b
cloneLens ALens' s a
l (p a (f a) -> Int -> a -> f a
forall i (p :: * -> * -> *) a b.
Indexable i p =>
p a b -> i -> a -> b
indexed p a (f a)
f (Int
0 :: Int))
{-# INLINE lensed #-}

-- | Step down into a 'Lens'. This is a constrained form of 'fromWithin' for when you know
-- there is precisely one target that can never fail.
--
-- @
-- 'downward' :: 'Lens'' s a -> (h ':>' s) -> h ':>' s ':>' a
-- 'downward' :: 'Iso'' s a  -> (h ':>' s) -> h ':>' s ':>' a
-- @
downward :: forall j h s a. ALens' s a -> h :> s:@j -> h :> s:@j :>> a
downward :: ALens' s a -> (h :> (s :@ j)) -> (h :> (s :@ j)) :>> a
downward ALens' s a
l (Zipper h t o p j s) = Coil (Zipper h j s) Int a
-> Int
-> Int
-> Path Int a
-> Int
-> a
-> Zipper (Zipper h j s) Int a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper (Coil h j s
-> AnIndexedTraversal' Int s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket Int a -> s)
-> Coil (Zipper h j s) Int a
forall i h j s a.
Ord i =>
Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
Snoc Coil h j s
h AnIndexedTraversal' Int s a
IndexedLens' Int s a
l' Int
t Int
o Path j s
p j
j Jacket Int a -> s
go) Int
0 Int
0 Path Int a
forall i a. Path i a
Start Int
0 (s
ss -> Getting a s a -> a
forall s a. s -> Getting a s a -> a
^.Getting a s a
IndexedLens' Int s a
l')
  where l' :: IndexedLens' Int s a
        l' :: p a (f a) -> s -> f s
l' = ALens' s a -> IndexedLens' Int s a
forall s a. ALens' s a -> IndexedLens' Int s a
lensed ALens' s a
l
        go :: Jacket Int a -> s
go (Leaf Int
_ a
b) = ASetter s s a a -> a -> s -> s
forall s t a b. ASetter s t a b -> b -> s -> t
set ASetter s s a a
IndexedLens' Int s a
l' a
b s
s
        go Jacket Int a
_ = String -> s
forall a. HasCallStack => String -> a
error String
"downward: rezipping"
{-# INLINE downward #-}

-- | Step down into a 'IndexedLens'. This is a constrained form of 'ifromWithin' for when you know
-- there is precisely one target that can never fail.
--
-- @
-- 'idownward' :: 'IndexedLens'' i s a -> (h ':>' s:\@j) -> h ':>' s:\@j ':>' a:\@i
-- @
idownward :: forall i j h s a. Ord i => AnIndexedLens' i s a -> h :> s:@j -> h :> s:@j :> a:@i
idownward :: AnIndexedLens' i s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :> (a :@ i)
idownward AnIndexedLens' i s a
l (Zipper h t o p j s) = Coil (Zipper h j s) i a
-> Int -> Int -> Path i a -> i -> a -> Zipper (Zipper h j s) i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper (Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
forall i h j s a.
Ord i =>
Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
Snoc Coil h j s
h AnIndexedTraversal' i s a
IndexedLens' i s a
l' Int
t Int
o Path j s
p j
j Jacket i a -> s
go) Int
0 Int
0 Path i a
forall i a. Path i a
Start i
i a
a
  where l' :: IndexedLens' i s a
        l' :: p a (f a) -> s -> f s
l' = AnIndexedLens' i s a -> IndexedLens' i s a
forall i s t a b. AnIndexedLens i s t a b -> IndexedLens i s t a b
cloneIndexedLens AnIndexedLens' i s a
l
        (i
i, a
a) = IndexedGetting i (i, a) s a -> s -> (i, a)
forall s (m :: * -> *) i a.
MonadReader s m =>
IndexedGetting i (i, a) s a -> m (i, a)
iview IndexedGetting i (i, a) s a
IndexedLens' i s a
l' s
s
        go :: Jacket i a -> s
go (Leaf i
_ a
b) = ASetter s s a a -> a -> s -> s
forall s t a b. ASetter s t a b -> b -> s -> t
set ASetter s s a a
IndexedLens' i s a
l' a
b s
s
        go Jacket i a
_ = String -> s
forall a. HasCallStack => String -> a
error String
"idownward: rezipping"
{-# INLINE idownward #-}

-- | Step down into the 'leftmost' entry of a 'Traversal'.
--
-- @
-- 'within' :: 'Traversal'' s a -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>>' a)
-- 'within' :: 'Prism'' s a     -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>>' a)
-- 'within' :: 'Lens'' s a      -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>>' a)
-- 'within' :: 'Iso'' s a       -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>>' a)
-- @
--
-- @
-- 'within' :: 'MonadPlus' m => 'ATraversal'' s a -> (h ':>' s:\@j) -> m (h ':>' s:\@j ':>>' a)
-- @
within :: MonadPlus m => LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a -> (h :> s:@j) -> m (h :> s:@j :>> a)
within :: LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :>> a)
within = AnIndexedTraversal' Int s a
-> Zipper h j s -> m (Zipper (Zipper h j s) Int a)
forall (m :: * -> *) i s a h j.
(MonadPlus m, Ord i) =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithin (AnIndexedTraversal' Int s a
 -> Zipper h j s -> m (Zipper (Zipper h j s) Int a))
-> (LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
    -> AnIndexedTraversal' Int s a)
-> LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> Zipper h j s
-> m (Zipper (Zipper h j s) Int a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> AnIndexedTraversal' Int s a
forall (p :: * -> * -> *) a (f :: * -> *) b s t.
Indexable Int p =>
((a -> Indexing f b) -> s -> Indexing f t) -> p a (f b) -> s -> f t
indexing
{-# INLINE within #-}

-- | Step down into the 'leftmost' entry of an 'IndexedTraversal'.
--
-- /Note:/ The index is assumed to be ordered and must increase monotonically or else you cannot (safely) 'moveTo' or 'moveToward' or use tapes.
--
-- @
-- 'iwithin' :: 'IndexedTraversal'' i s a -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>' a:\@i)
-- 'iwithin' :: 'IndexedLens'' i s a      -> (h ':>' s:\@j) -> 'Maybe' (h ':>' s:\@j ':>' a:\@i)
-- @
--
-- @
-- 'iwithin' :: 'MonadPlus' m => 'ATraversal'' s a -> (h ':>' s:\@j) -> m (h ':>' s:\@j ':>>' a)
-- @
iwithin :: (MonadPlus m, Ord i) => AnIndexedTraversal' i s a -> (h :> s:@j) -> m (h :> s:@j :> a:@i)
iwithin :: AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithin AnIndexedTraversal' i s a
l (Zipper h t o p j s) = case AnIndexedTraversal' i s a
-> (Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a))
-> s
-> Context (Jacket i a) (Jacket i a) s
forall i s t a b j.
AnIndexedTraversal i s t a b -> Lens s t (Jacket i a) (Jacket j b)
jacket AnIndexedTraversal' i s a
l ((Jacket i a -> Jacket i a)
-> Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a)
forall a b t. (b -> t) -> a -> Context a b t
Context Jacket i a -> Jacket i a
forall a. a -> a
id) s
s of
  Context Jacket i a -> s
k Jacket i a
xs -> Path i a
-> Jacket i a
-> m (Zipper (Zipper h j s) i a)
-> (Path i a -> i -> a -> m (Zipper (Zipper h j s) i a))
-> m (Zipper (Zipper h j s) i a)
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl Path i a
forall i a. Path i a
Start Jacket i a
xs m (Zipper (Zipper h j s) i a)
forall (m :: * -> *) a. MonadPlus m => m a
mzero ((Path i a -> i -> a -> m (Zipper (Zipper h j s) i a))
 -> m (Zipper (Zipper h j s) i a))
-> (Path i a -> i -> a -> m (Zipper (Zipper h j s) i a))
-> m (Zipper (Zipper h j s) i a)
forall a b. (a -> b) -> a -> b
$ \Path i a
q i
i a
a -> Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a))
-> Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a)
forall a b. (a -> b) -> a -> b
$ Coil (Zipper h j s) i a
-> Int -> Int -> Path i a -> i -> a -> Zipper (Zipper h j s) i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper (Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
forall i h j s a.
Ord i =>
Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
Snoc Coil h j s
h AnIndexedTraversal' i s a
l Int
t Int
o Path j s
p j
j Jacket i a -> s
k) Int
0 Int
0 Path i a
q i
i a
a
{-# INLINE iwithin #-}

-- | Step down into every entry of a 'Traversal' simultaneously.
--
-- >>> zipper ("hello","world") & withins both >>= leftward >>= withins traverse >>= rightward <&> focus %~ toUpper <&> rezip :: [(String,String)]
-- [("hEllo","world"),("heLlo","world"),("helLo","world"),("hellO","world")]
--
-- @
-- 'withins' :: 'Traversal'' s a -> (h ':>' s:\@j) -> [h ':>' s:\@j ':>>' a]
-- 'withins' :: 'Lens'' s a      -> (h ':>' s:\@j) -> [h ':>' s:\@j ':>>' a]
-- 'withins' :: 'Iso'' s a       -> (h ':>' s:\@j) -> [h ':>' s:\@j ':>>' a]
-- @
withins :: MonadPlus m => LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a -> (h :> s:@j) -> m (h :> s:@j :>> a)
withins :: LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :>> a)
withins = AnIndexedTraversal' Int s a
-> Zipper h j s -> m (Zipper (Zipper h j s) Int a)
forall (m :: * -> *) i s a h j.
(MonadPlus m, Ord i) =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithins (AnIndexedTraversal' Int s a
 -> Zipper h j s -> m (Zipper (Zipper h j s) Int a))
-> (LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
    -> AnIndexedTraversal' Int s a)
-> LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> Zipper h j s
-> m (Zipper (Zipper h j s) Int a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> AnIndexedTraversal' Int s a
forall (p :: * -> * -> *) a (f :: * -> *) b s t.
Indexable Int p =>
((a -> Indexing f b) -> s -> Indexing f t) -> p a (f b) -> s -> f t
indexing
{-# INLINE withins #-}

-- | Step down into every entry of an 'IndexedTraversal' simultaneously.
--
-- /Note:/ The index is assumed to be ordered and must increase monotonically or else you cannot (safely) 'moveTo' or 'moveToward' or use tapes.
--
-- @
-- 'iwithins' :: 'IndexedTraversal'' i s a -> (h ':>' s:\@j) -> [h ':>' s:\@j ':>' a:\@i]
-- 'iwithins' :: 'IndexedLens'' i s a      -> (h ':>' s:\@j) -> [h ':>' s:\@j ':>' a:\@i]
-- @
iwithins :: (MonadPlus m, Ord i) => AnIndexedTraversal' i s a -> (h :> s:@j) -> m (h :> s:@j :> a:@i)
iwithins :: AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithins AnIndexedTraversal' i s a
z (Zipper h t o p j s) = case AnIndexedTraversal' i s a
-> (Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a))
-> s
-> Context (Jacket i a) (Jacket i a) s
forall i s t a b j.
AnIndexedTraversal i s t a b -> Lens s t (Jacket i a) (Jacket j b)
jacket AnIndexedTraversal' i s a
z ((Jacket i a -> Jacket i a)
-> Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a)
forall a b t. (b -> t) -> a -> Context a b t
Context Jacket i a -> Jacket i a
forall a. a -> a
id) s
s of
  Context Jacket i a -> s
k Jacket i a
xs -> let up :: Coil (Zipper h j s) i a
up = Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
forall i h j s a.
Ord i =>
Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
Snoc Coil h j s
h AnIndexedTraversal' i s a
z Int
t Int
o Path j s
p j
j Jacket i a -> s
k
                      go :: Path i a -> Jacket i a -> m (Zipper (Zipper h j s) i a)
go Path i a
q (Ap Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Jacket i a
r) = Path i a -> Jacket i a -> m (Zipper (Zipper h j s) i a)
go (Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Path i a -> Jacket i a -> Path i a
ApL Int
m Bool
nl Bool
nr Last i
li Path i a
q Jacket i a
r) Jacket i a
l m (Zipper (Zipper h j s) i a)
-> m (Zipper (Zipper h j s) i a) -> m (Zipper (Zipper h j s) i a)
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Path i a -> Jacket i a -> m (Zipper (Zipper h j s) i a)
go (Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
forall i a.
Int -> Bool -> Bool -> Last i -> Jacket i a -> Path i a -> Path i a
ApR Int
m Bool
nl Bool
nr Last i
li Jacket i a
l Path i a
q) Jacket i a
r
                      go Path i a
q (Leaf i
i a
a)       = Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a))
-> Zipper (Zipper h j s) i a -> m (Zipper (Zipper h j s) i a)
forall a b. (a -> b) -> a -> b
$ Coil (Zipper h j s) i a
-> Int -> Int -> Path i a -> i -> a -> Zipper (Zipper h j s) i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil (Zipper h j s) i a
up (Path i a -> Int
forall i a. Path i a -> Int
offset Path i a
q) Int
0 Path i a
q i
i a
a
                      go Path i a
_ Jacket i a
Pure             = m (Zipper (Zipper h j s) i a)
forall (m :: * -> *) a. MonadPlus m => m a
mzero
                  in  Path i a -> Jacket i a -> m (Zipper (Zipper h j s) i a)
go Path i a
forall i a. Path i a
Start Jacket i a
xs
{-# INLINE iwithins #-}

-- | Unsafely step down into a 'Traversal' that is /assumed/ to be non-empty.
--
-- If this invariant is not met then this will usually result in an error!
--
-- @
-- 'fromWithin' :: 'Traversal'' s a -> (h ':>' s:\@j) -> h ':>' s:\@j ':>>' a
-- 'fromWithin' :: 'Lens'' s a      -> (h ':>' s:\@j) -> h ':>' s:\@j ':>>' a
-- 'fromWithin' :: 'Iso'' s a       -> (h ':>' s:\@j) -> h ':>' s:\@j ':>>' a
-- @
--
-- You can reason about this function as if the definition was:
--
-- @
-- 'fromWithin' l ≡ 'fromJust' '.' 'within' l
-- @
fromWithin :: LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a -> (h :> s:@j) -> h :> s:@j :>> a
fromWithin :: LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :>> a
fromWithin = AnIndexedTraversal' Int s a
-> Zipper h j s -> Zipper (Zipper h j s) Int a
forall i s a h j.
Ord i =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :> (a :@ i)
ifromWithin (AnIndexedTraversal' Int s a
 -> Zipper h j s -> Zipper (Zipper h j s) Int a)
-> (LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
    -> AnIndexedTraversal' Int s a)
-> LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> Zipper h j s
-> Zipper (Zipper h j s) Int a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike' (Indexing (Bazaar' (Indexed Int) a)) s a
-> AnIndexedTraversal' Int s a
forall (p :: * -> * -> *) a (f :: * -> *) b s t.
Indexable Int p =>
((a -> Indexing f b) -> s -> Indexing f t) -> p a (f b) -> s -> f t
indexing
{-# INLINE fromWithin #-}

-- | Unsafey step down into an 'IndexedTraversal' that is /assumed/ to be non-empty
--
-- If this invariant is not met then this will usually result in an error!
--
-- @
-- 'ifromWithin' :: 'IndexedTraversal'' i s a -> (h ':>' s:\@j) -> h ':>' s:\@j ':>' a:\@i
-- 'ifromWithin' :: 'IndexedLens'' i s a      -> (h ':>' s:\@j) -> h ':>' s:\@j ':>' a:\@i
-- @
--
-- You can reason about this function as if the definition was:
--
-- @
-- 'fromWithin' l ≡ 'fromJust' '.' 'within' l
-- @
ifromWithin :: Ord i => AnIndexedTraversal' i s a -> (h :> s:@j) -> h :> s:@j :> a:@i
ifromWithin :: AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :> (a :@ i)
ifromWithin AnIndexedTraversal' i s a
l (Zipper h t o p j s) = case AnIndexedTraversal' i s a
-> (Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a))
-> s
-> Context (Jacket i a) (Jacket i a) s
forall i s t a b j.
AnIndexedTraversal i s t a b -> Lens s t (Jacket i a) (Jacket j b)
jacket AnIndexedTraversal' i s a
l ((Jacket i a -> Jacket i a)
-> Jacket i a -> Context (Jacket i a) (Jacket i a) (Jacket i a)
forall a b t. (b -> t) -> a -> Context a b t
Context Jacket i a -> Jacket i a
forall a. a -> a
id) s
s of
  Context Jacket i a -> s
k Jacket i a
xs -> let up :: Coil (Zipper h j s) i a
up = Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
forall i h j s a.
Ord i =>
Coil h j s
-> AnIndexedTraversal' i s a
-> Int
-> Int
-> Path j s
-> j
-> (Jacket i a -> s)
-> Coil (Zipper h j s) i a
Snoc Coil h j s
h AnIndexedTraversal' i s a
l Int
t Int
o Path j s
p j
j Jacket i a -> s
k in
    Path i a
-> Jacket i a
-> Zipper (Zipper h j s) i a
-> (Path i a -> i -> a -> Zipper (Zipper h j s) i a)
-> Zipper (Zipper h j s) i a
forall i a r.
Path i a -> Jacket i a -> r -> (Path i a -> i -> a -> r) -> r
startl Path i a
forall i a. Path i a
Start Jacket i a
xs (Coil (Zipper h j s) i a
-> Int -> Int -> Path i a -> i -> a -> Zipper (Zipper h j s) i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil (Zipper h j s) i a
up Int
0 Int
0 Path i a
forall i a. Path i a
Start (String -> i
forall a. HasCallStack => String -> a
error String
"fromWithin an empty Traversal")
                                         (String -> a
forall a. HasCallStack => String -> a
error String
"fromWithin an empty Traversal"))
                    (Coil (Zipper h j s) i a
-> Int -> Int -> Path i a -> i -> a -> Zipper (Zipper h j s) i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil (Zipper h j s) i a
up Int
0 Int
0)
{-# INLINE ifromWithin #-}

-- | This enables us to pull the 'Zipper' back up to the 'Top'.
class Zipping h a where
  recoil :: Coil h i a -> Jacket i a -> Zipped h a

instance Zipping Top a where
  recoil :: Coil Top i a -> Jacket i a -> Zipped Top a
recoil Coil Top i a
Coil (Leaf i
_ a
a) = a
Zipped Top a
a
  recoil Coil Top i a
Coil Jacket i a
_ = String -> a
forall a. HasCallStack => String -> a
error String
"recoil: expected Leaf"
  {-# INLINE recoil #-}

instance Zipping h s => Zipping (Zipper h i s) a where
  recoil :: Coil (Zipper h i s) i a -> Jacket i a -> Zipped (Zipper h i s) a
recoil (Snoc Coil h j s
h AnIndexedTraversal' i s a
_ Int
_ Int
_ Path j s
p j
i Jacket i a -> s
k) Jacket i a
as = Coil h j s -> Jacket j s -> Zipped h s
forall h a i. Zipping h a => Coil h i a -> Jacket i a -> Zipped h a
recoil Coil h j s
h (Jacket j s -> Zipped h s) -> Jacket j s -> Zipped h s
forall a b. (a -> b) -> a -> b
$ Path j s -> j -> s -> Jacket j s
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path j s
p j
i (Jacket i a -> s
k Jacket i a
as)
  {-# INLINE recoil #-}

-- | Close something back up that you opened as a 'Zipper'.
rezip :: Zipping h a => (h :> a:@i) -> Zipped h a
rezip :: (h :> (a :@ i)) -> Zipped h a
rezip (Zipper h _ _ p i a) = Coil h i a -> Jacket i a -> Zipped h a
forall h a i. Zipping h a => Coil h i a -> Jacket i a -> Zipped h a
recoil Coil h i a
h (Path i a -> i -> a -> Jacket i a
forall i a. Path i a -> i -> a -> Jacket i a
recompress Path i a
p i
i a
a)
{-# INLINE rezip #-}

-- | Extract the current 'focus' from a 'Zipper' as a 'Pretext', with access to the current index.
focusedContext :: (Indexable i p, Zipping h a) => (h :> a:@i) -> Pretext p a a (Zipped h a)
focusedContext :: (h :> (a :@ i)) -> Pretext p a a (Zipped h a)
focusedContext (Zipper h t o p i a) = (forall (f :: * -> *). Functor f => p a (f a) -> f (Zipped h a))
-> Pretext p a a (Zipped h a)
forall (p :: * -> * -> *) a b t.
(forall (f :: * -> *). Functor f => p a (f b) -> f t)
-> Pretext p a b t
Pretext (\p a (f a)
f -> Zipper h i a -> Zipped h a
forall h a i. Zipping h a => (h :> (a :@ i)) -> Zipped h a
rezip (Zipper h i a -> Zipped h a)
-> (a -> Zipper h i a) -> a -> Zipped h a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
forall h i a.
Ord i =>
Coil h i a -> Int -> Int -> Path i a -> i -> a -> Zipper h i a
Zipper Coil h i a
h Int
t Int
o Path i a
p i
i (a -> Zipped h a) -> f a -> f (Zipped h a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p a (f a) -> i -> a -> f a
forall i (p :: * -> * -> *) a b.
Indexable i p =>
p a b -> i -> a -> b
indexed p a (f a)
f i
i a
a)
{-# INLINE focusedContext #-}

-----------------------------------------------------------------------------
-- * Tapes
-----------------------------------------------------------------------------

-- | A 'Tape' is a recorded path through the (indexed) 'Traversal' chain of a 'Zipper'.
data Tape h i a where
  Tape :: Track h i a -> i -> Tape h i a

-- | Save the current path as as a 'Tape' we can play back later.
saveTape :: Zipper h i a -> Tape h i a
saveTape :: Zipper h i a -> Tape h i a
saveTape (Zipper Coil h i a
h Int
_ Int
_ Path i a
_ i
i a
_) = Track h i a -> i -> Tape h i a
forall h i a. Track h i a -> i -> Tape h i a
Tape (Coil h i a -> Track h i a
forall h i a. Coil h i a -> Track h i a
peel Coil h i a
h) i
i
{-# INLINE saveTape #-}

-- | Restore ourselves to a previously recorded position precisely.
--
-- If the position does not exist, then fail.
restoreTape :: MonadPlus m => Tape h i a -> Zipped h a -> m (Zipper h i a)
restoreTape :: Tape h i a -> Zipped h a -> m (Zipper h i a)
restoreTape (Tape Track h i a
h i
n) = Track h i a -> Zipped h a -> m (Zipper h i a)
forall (m :: * -> *) h i a.
MonadPlus m =>
Track h i a -> Zipped h a -> m (Zipper h i a)
restoreTrack Track h i a
h (Zipped h a -> m (Zipper h i a))
-> (Zipper h i a -> m (Zipper h i a))
-> Zipped h a
-> m (Zipper h i a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> i -> (h :> (a :@ i)) -> m (h :> (a :@ i))
forall (m :: * -> *) i h a.
MonadPlus m =>
i -> (h :> (a :@ i)) -> m (h :> (a :@ i))
moveTo i
n
{-# INLINE restoreTape #-}

-- | Restore ourselves to a location near our previously recorded position.
--
-- When moving left to right through a 'Traversal', if this will clamp at each
-- level to the range @0 '<=' k '<' 'teeth'@, so the only failures will occur
-- when one of the sequence of downward traversals find no targets.
restoreNearTape :: MonadPlus m => Tape h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTape :: Tape h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTape (Tape Track h i a
h i
n) Zipped h a
a = (Zipper h i a -> Zipper h i a)
-> m (Zipper h i a) -> m (Zipper h i a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (i -> (h :> (a :@ i)) -> h :> (a :@ i)
forall i h a. i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward i
n) (Track h i a -> Zipped h a -> m (Zipper h i a)
forall (m :: * -> *) h i a.
MonadPlus m =>
Track h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTrack Track h i a
h Zipped h a
a)
{-# INLINE restoreNearTape #-}

-- | Restore ourselves to a previously recorded position.
--
-- This *assumes* that nothing has been done in the meantime to affect the existence of anything on the entire path.
--
-- Motions 'leftward' or 'rightward' are clamped, but all traversals included on the 'Tape' are assumed to be non-empty.
--
-- Violate these assumptions at your own risk!
unsafelyRestoreTape :: Tape h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTape :: Tape h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTape (Tape Track h i a
h i
n) = Track h i a -> Zipped h a -> Zipper h i a
forall h i a. Track h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTrack Track h i a
h (Zipped h a -> Zipper h i a)
-> (Zipper h i a -> Zipper h i a) -> Zipped h a -> Zipper h i a
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> i -> (h :> (a :@ i)) -> h :> (a :@ i)
forall i h a. i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward i
n
{-# INLINE unsafelyRestoreTape #-}

-----------------------------------------------------------------------------
-- * Tracks
-----------------------------------------------------------------------------

-- | This is used to peel off the path information from a 'Coil' for use when saving the current path for later replay.
peel :: Coil h i a -> Track h i a
peel :: Coil h i a -> Track h i a
peel Coil h i a
Coil             = Track h i a
forall a. Track Top Int a
Track
peel (Snoc Coil h j s
h AnIndexedTraversal' i s a
l Int
_ Int
_ Path j s
_ j
i Jacket i a -> s
_) = Track h j s
-> j -> AnIndexedTraversal' i s a -> Track (Zipper h j s) i a
forall i h j s a.
Ord i =>
Track h j s
-> j -> AnIndexedTraversal' i s a -> Track (Zipper h j s) i a
Fork (Coil h j s -> Track h j s
forall h i a. Coil h i a -> Track h i a
peel Coil h j s
h) j
i AnIndexedTraversal' i s a
l
{-# INLINE peel #-}

-- | The 'Track' forms the bulk of a 'Tape'.
data Track t i a where
  Track :: Track Top Int a
  Fork  :: Ord i => Track h j s -> j -> AnIndexedTraversal' i s a -> Track (Zipper h j s) i a

-- | Restore ourselves to a previously recorded position precisely.
--
-- If the position does not exist, then fail.
restoreTrack :: MonadPlus m => Track h i a -> Zipped h a -> m (Zipper h i a)
restoreTrack :: Track h i a -> Zipped h a -> m (Zipper h i a)
restoreTrack Track h i a
Track        = (Top :>> a) -> m (Top :>> a)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Top :>> a) -> m (Top :>> a))
-> (a -> Top :>> a) -> a -> m (Top :>> a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Top :>> a
forall a. a -> Top :>> a
zipper
restoreTrack (Fork Track h j s
h j
n AnIndexedTraversal' i s a
l) = Track h j s -> Zipped h s -> m (Zipper h j s)
forall (m :: * -> *) h i a.
MonadPlus m =>
Track h i a -> Zipped h a -> m (Zipper h i a)
restoreTrack Track h j s
h (Zipped h s -> m (Zipper h j s))
-> (Zipper h j s -> m (Zipper h i a))
-> Zipped h s
-> m (Zipper h i a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> j -> (h :> (s :@ j)) -> m (h :> (s :@ j))
forall (m :: * -> *) i h a.
MonadPlus m =>
i -> (h :> (a :@ i)) -> m (h :> (a :@ i))
moveTo j
n (Zipper h j s -> m (Zipper h j s))
-> (Zipper h j s -> m (Zipper h i a))
-> Zipper h j s
-> m (Zipper h i a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
forall (m :: * -> *) i s a h j.
(MonadPlus m, Ord i) =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithin AnIndexedTraversal' i s a
l

-- | Restore ourselves to a location near our previously recorded position.
--
-- When moving 'leftward' to 'rightward' through a 'Traversal', if this will clamp at each level to the range @0 '<=' k '<' 'teeth'@,
-- so the only failures will occur when one of the sequence of downward traversals find no targets.
restoreNearTrack :: MonadPlus m => Track h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTrack :: Track h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTrack Track h i a
Track        = (Top :>> a) -> m (Top :>> a)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Top :>> a) -> m (Top :>> a))
-> (a -> Top :>> a) -> a -> m (Top :>> a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Top :>> a
forall a. a -> Top :>> a
zipper
restoreNearTrack (Fork Track h j s
h j
n AnIndexedTraversal' i s a
l) = Track h j s -> Zipped h s -> m (Zipper h j s)
forall (m :: * -> *) h i a.
MonadPlus m =>
Track h i a -> Zipped h a -> m (Zipper h i a)
restoreNearTrack Track h j s
h (Zipped h s -> m (Zipper h j s))
-> (Zipper h j s -> m (Zipper h i a))
-> Zipped h s
-> m (Zipper h i a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> j -> (h :> (s :@ j)) -> h :> (s :@ j)
forall i h a. i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward j
n (Zipper h j s -> Zipper h j s)
-> (Zipper h j s -> m (Zipper (Zipper h j s) i a))
-> Zipper h j s
-> m (Zipper (Zipper h j s) i a)
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
forall (m :: * -> *) i s a h j.
(MonadPlus m, Ord i) =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> m ((h :> (s :@ j)) :> (a :@ i))
iwithin AnIndexedTraversal' i s a
l

-- | Restore ourselves to a previously recorded position.
--
-- This *assumes* that nothing has been done in the meantime to affect the existence of anything on the entire 'Path'.
--
-- Motions 'leftward' or 'rightward' are clamped, but all traversals included on the 'Tape' are assumed to be non-empty.
--
-- Violate these assumptions at your own risk!
unsafelyRestoreTrack :: Track h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTrack :: Track h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTrack Track h i a
Track = Zipped h a -> Zipper h i a
forall a. a -> Top :>> a
zipper
unsafelyRestoreTrack (Fork Track h j s
h j
n AnIndexedTraversal' i s a
l) = Track h j s -> Zipped h s -> Zipper h j s
forall h i a. Track h i a -> Zipped h a -> Zipper h i a
unsafelyRestoreTrack Track h j s
h (Zipped h s -> Zipper h j s)
-> (Zipper h j s -> Zipper (Zipper h j s) i a)
-> Zipped h s
-> Zipper (Zipper h j s) i a
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> j -> (h :> (s :@ j)) -> h :> (s :@ j)
forall i h a. i -> (h :> (a :@ i)) -> h :> (a :@ i)
moveToward j
n (Zipper h j s -> Zipper h j s)
-> (Zipper h j s -> Zipper (Zipper h j s) i a)
-> Zipper h j s
-> Zipper (Zipper h j s) i a
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :> (a :@ i)
forall i s a h j.
Ord i =>
AnIndexedTraversal' i s a
-> (h :> (s :@ j)) -> (h :> (s :@ j)) :> (a :@ i)
ifromWithin AnIndexedTraversal' i s a
l