@@ -38,14 +38,19 @@ module Data.Zipper.ArrayZipper
38
38
39
39
import Prelude
40
40
41
+ import Control.Comonad (class Comonad )
42
+ import Control.Extend (class Extend )
43
+ import Control.Monad.Gen (chooseInt )
41
44
import Data.Array (findIndex , length , mapWithIndex , unsafeIndex )
45
+ import Data.Array.NonEmpty as NEA
42
46
import Data.Foldable (class Foldable , foldMapDefaultL , foldl , foldr )
43
47
import Data.FoldableWithIndex (class FoldableWithIndex , foldMapWithIndex , foldlWithIndex , foldrWithIndex )
44
48
import Data.FunctorWithIndex (class FunctorWithIndex )
45
49
import Data.Maybe (Maybe (..), fromMaybe )
46
50
import Data.Traversable (class Traversable , sequenceDefault , traverse )
47
51
import Data.TraversableWithIndex (class TraversableWithIndex , traverseWithIndex )
48
52
import Partial.Unsafe (unsafePartial )
53
+ import Test.QuickCheck.Arbitrary (class Arbitrary , class Coarbitrary , arbitrary , coarbitrary )
49
54
50
55
-- | An immutable Zipper for an Array. Modifications are `O(n)` due to creating
51
56
-- | a new array rather than mutating the underlying array. Navigating to a
@@ -89,6 +94,16 @@ instance traversableWithIndex :: TraversableWithIndex Int ArrayZipper where
89
94
ar <- traverseWithIndex f r.array
90
95
in (ArrayZipper r { array = ar })
91
96
97
+ instance extendArrayZipper :: Extend ArrayZipper where
98
+ extend :: forall b a . (ArrayZipper a -> b ) -> ArrayZipper a -> ArrayZipper b
99
+ extend f (ArrayZipper rec) =
100
+ let allFoci idx _ = f (ArrayZipper rec { focusIndex = idx })
101
+ in ArrayZipper (rec { array = mapWithIndex allFoci rec.array})
102
+
103
+ instance comonadArrayZipper :: Comonad ArrayZipper where
104
+ extract :: forall a . ArrayZipper a -> a
105
+ extract = getFocus
106
+
92
107
-- | Creates an Array Zipper from a single element. This will be stored
93
108
-- | internally as a 1-element array. To further build upon this array,
94
109
-- | see `push*` functions.
@@ -281,3 +296,17 @@ pushNextRefocus a (ArrayZipper r) =
281
296
, maxIndex = r.maxIndex + 1
282
297
, array = unsafeInsertAt (r.focusIndex + 1 ) a r.array
283
298
}
299
+
300
+ -- Test-related items
301
+ instance arbitraryArrayZipper :: Arbitrary a => Arbitrary (ArrayZipper a ) where
302
+ arbitrary = do
303
+ array <- NEA .toArray <$> arbitrary
304
+ let maxIndex = length array - 1
305
+ focusIndex <- chooseInt 0 maxIndex
306
+ pure $ ArrayZipper { array, focusIndex, maxIndex }
307
+
308
+ instance coarbitraryArrayZipper :: Coarbitrary a => Coarbitrary (ArrayZipper a ) where
309
+ coarbitrary (ArrayZipper r) =
310
+ coarbitrary r.array >>>
311
+ coarbitrary r.maxIndex >>>
312
+ coarbitrary r.focusIndex
0 commit comments