¿Cómo indexar un tipo de "elemento" por un valor de "contenedor de origen"?

Así que tengo una situación muy similar a este código (muy simplificado):

import Data.Maybe
import Data.List

data Container a = Container [a] 

-- Assumption: an Element can only obtained from a Container.  The operation
-- guarentees the Element is in the Container.
data Element a = Element (Container a) a

-- This operation is only valid for Elements that have the same Container.
before :: Eq a => Element a -> Element a -> Bool
before (Element (Container xs) x) (Element (Container ys) y) 
    | xs == ys = fromJust (elemIndex x xs) < fromJust (elemIndex y xs)
    | otherwise = error "Elements from different Containers"

¿Cómo puedo usar el sistema de tipos de Haskell (o las extensiones de GHC) para restringirbefore y operaciones similares de tomarElements de diferenteContainers? He estado investigandoGADTs yDataKinds pero, bueno, eso va a llevar mucho tiempo y podría usar algunas sugerencias o sugerencias. (Otra idea que he pensado, pero no he trabajado: usa un truco similar al deST mónadas parámetro...)

¿Soy demasiado pesimista si llego a la conclusión de que esto requeriría un lenguaje tipificado de manera dependiente? Porque, como mi comprensión limitada de la tipificación dependiente va, creo que estoy tratando de indexar elElement tipo por valores de laContainer tipo.

EDITAR: Solo para color adicional, todo esto surge en última instancia porque estoy tratando de definir algo muy parecido a esto:

import Data.Function
import Data.Ix

-- I want to use Elements as Array indexes; so Elements need to know
-- their Container to calculate their Int
instance Eq a => Ix (Element a) where
    -- Ignore how crap this code is
    range (l, u) = map (getSibling l) [getIndex l .. getIndex u]
    index (l,u) i = index (getIndex l, getIndex u) (getIndex i)
    inRange (l,u) i = inRange (getIndex l, getIndex u) (getIndex i)

getIndex :: Eq a => Element a -> Int
getIndex (Element (Container xs) x) = fromJust $ elemIndex x xs

getList :: Element a -> [a]
getList (Element (Container xs) _) = xs

getSibling :: Element a -> Int -> Element a
getSibling (Element (Container xs) _) i = Element (Container xs) (xs!!i)

instance Eq a => Eq (Element a) where
    (==) = (==) `on` getIndex

instance Eq a => Ord (Element a) where
    compare = compare `on` getIndex

Todo este código requiere que nunca se "mezcle"Elements de diferenteContainers.

Respuestas a la pregunta(2)

Su respuesta a la pregunta