## Context

A while ago, I implemented an immutable Array-based Zipper. I’m now adding instances for the `Extend`

and `Comonad`

type class instances. However, when I use `quickcheck-laws`

to verify that these instances are correct, the Comonad check fails:

```
Checking 'Associativity' law for Extend
1000/1000 test(s) passed.
✓︎ Extend
Checking 'Left identity' law for Comonad
1000/1000 test(s) passed.
Checking 'Right identity' law for Comonad
491/1000 test(s) passed.
✗ Comonad:
Test 3 (seed 1808572881) failed:
Test returned false
```

## Overview of Problem

Comonad’s `extract`

is pretty easy to implement, and after further debugging I can prove that the issue is with my `Extend`

implementation. The below implementation fails because I always set the `focusIndex`

to `0`

(so that a valid element is always focused regardless of which index I use). This implementation works fine when the first element is focused, but fails when any other element is focused.

So, if I have an array `[0, 1, 2]`

, and I focus the third element (i.e. `2`

), then this equation should be true:

```
extract (extend (fold $ map Additive) zipper) == (fold $ map Additive) zipper
```

It’s not because the first iteration of `mapWithIndex`

below will “copy” the zipper into the first element slot in the array. In reality, it should be copied into the third element slot in the array.

While I could use a custom case to force that to occur, I’m guessing my understanding of what this instance should be doing is likely just incorrect in the first place.

**Could someone clarify how the Extend instance should be implemented?**

## Current Implementation

I based my implementation on the Array instance. For a runnable example, I put a gist together via Try PureScript. You’ll need to open the console to see the result.

```
-- | An immutable Zipper for an Array.
-- | Modifications to the focused element are `O(n)` due to creating
-- | a new array rather than mutating the underlying array.
-- | Navigating to a new focus element is `O(1)` regardless of how far
-- | away from the current focus that element is. This
-- | is in contrast to a `List`-based zipper where modifications
-- | are `O(1)` and navigation is `O(n)`.
-- |
-- | In other words, this zipper works well in read-heavy code
-- | but might not work well in write-heavy code
-- |
-- | [0, 1, 2, 3, 4, 5]
-- | ^ ^
-- | | -- maxIndex
-- | -- focusIndex
newtype ArrayZipper a =
ArrayZipper { array :: Array a, focusIndex :: Int, maxIndex :: Int }
derive instance eqArrayZipper :: Eq a => Eq (ArrayZipper a)
derive instance functorArrayZipper :: Functor ArrayZipper
instance extendArrayZipper :: Extend ArrayZipper where
extend
:: forall b a
. (ArrayZipper a -> b)
-> ArrayZipper a
-> ArrayZipper b
extend f (ArrayZipper rec) =
let
sliceArray idx _ =
f (ArrayZipper
{ array: slice idx (rec.maxIndex + 1) rec.array
, focusIndex: 0
, maxIndex: rec.maxIndex - idx
})
in ArrayZipper (rec { array = mapWithIndex sliceArray rec.array})
instance comonadArrayZipper :: Comonad ArrayZipper where
extract :: forall a. ArrayZipper a -> a
extract (ArrayZipper r) = unsafePartial (unsafeIndex r.array r.focusIndex)
```

## Other `Extend`

implementations I’ve tried

This implementation fails to pass the same law above. It duplicates the zipper `n`

times, so that each copy is focusing a different element within it:

```
instance extendArrayZipper :: Extend ArrayZipper where
extend
:: forall b a
. (ArrayZipper a -> b)
-> ArrayZipper a
-> ArrayZipper b
extend f (ArrayZipper rec) =
let
sliceZipper idx _ =
f (ArrayZipper rec { focusIndex = idx })
in ArrayZipper (rec { array = mapWithIndex sliceZipper rec.array})
```