fill p t@(IOA m _) = go
  where
    go i j
      | i < m - 1  = do
          pi <- getIO p (id i)
          pj <- getIO p j
          case () of
            _ | pi == pj -> do
                  let i' = i + 1
                  let j' = j + 1
                  setIO t i' j'
                  go i' j'
              | j == 0 -> do
                  let i' = i + 1
                  setIO t i' 0
                  go i' j
              | otherwise -> do
                  j' <- getIO t j
                  go i j'
      | otherwise = return t


-------------------------------------------------------------------------------
-- | An Imperative Array ------------------------------------------------------
-------------------------------------------------------------------------------
fill p t@(IOA m _) = go
  where
    go i j
      | i < m - 1  = do
          pi <- getIO p (id i)
          pj <- getIO p j
          case () of
            _ | pi == pj -> do
                  let i' = i + 1
                  let j' = j + 1
                  setIO t i' j'
                  go i' j'
              | j == 0 -> do
                  let i' = i + 1
                  setIO t i' 0
                  go i' j
              | otherwise -> do
                  j' <- getIO t j
                  go i j'
      | otherwise = return t


-------------------------------------------------------------------------------
-- | An Imperative Array ------------------------------------------------------
-------------------------------------------------------------------------------
fill p t@(IOA m _) = go
  where
    go i j
      | i < m - 1  = do
          pi <- getIO p (id i)
          pj <- getIO p j
          case () of
            _ | pi == pj -> do
                  let i' = i + 1
                  let j' = j + 1
                  setIO t i' j'
                  go i' j'
              | j == 0 -> do
                  let i' = i + 1
                  setIO t i' 0
                  go i' j
              | otherwise -> do
                  j' <- getIO t j
                  go i j'
      | otherwise = return t


-------------------------------------------------------------------------------
-- | An Imperative Array ------------------------------------------------------
-------------------------------------------------------------------------------