<div dir="ltr">Hello all,<div><br></div><div>I put together a small library for the purpose of creating overloaded indexing operators. The library is available at <a href="https://hackage.haskell.org/package/keyed" target="_blank">https://hackage.haskell.org/package/keyed</a> .</div><div><br></div><div>I would like to solicit some advice on the design of this library.</div><div><br></div><div>Q1:</div><div>The library uses TypeFamilies to determine which types to use for the index type (which is used to look up a value) and the value type (which is returned from a lookup).</div><div><br></div><div>I originally did this using MultiParamTypeClasses and FunctionalDependencies, but thought this was cleaner; are there any good reasons to go back to using FunDeps?</div><div><br></div><div>Q2:</div><div>Data.Keyed provides pure indexing, while Data.MKeyed provides monadic indexing (e.g. for mutable vectors or concurrent STM-based maps).</div><div><br></div><div>I'm having some trouble with the fact that mutable vectors are keyed on the PrimState of their corresponding PrimMonad. </div><div><br></div><div>Right now, there is a type in the MKeyed class definition called MContainer. This is the type of the Monad that the lookup operation returns. I.e.</div><div><br></div><div>(!) :: MKeyed d => d -> MKey d -> MContainer d (MValue d)</div><div>~</div><div>(!) :: IOVector a -> Int -> IO a</div><div>or</div><div>(!) :: STVector s a -> Int -> ST s a<br></div><div><br></div><div>Unfortunately, this causes an overlap (because both IOVector and STVector are aliased to MVector).</div><div><br></div><div>I tried making an instance for MVector, but the problem is that it's difficult to actually go from `IOVector a = MVector RealWorld a` to `IO` or `STVector s a = MVector s a` to `ST`, because neither `IO` nor `ST` appears in the type of the vector. I can't do<br></div><div><br></div><div>instance (PrimMonad m, s ~ PrimState m) => MKeyed (MVector s a) where ...</div><div>    type MContainer (MVector (PrimState m) a) = m</div><div><br></div><div>because you can't have type synonyms on the LHS of the type.</div><div><br></div><div>I tried bringing `m` into scope using RankNTypes, but that didn't work.</div><div><br></div><div>Is there some syntax I can use to bring `m` into scope here?</div><div><br></div><div>Or should I be doing this part entirely differently?</div><div><br></div><div>Q3:</div><div>Is there any way to automatically derive all instances of Keyed for all types of Data.Vector (using Data.Vector.Generic)? Using `instance Vector v a => Keyed (v a) where ...` doesn't work, as it overlaps with everything of the form `(d :: * -> *) (a :: *) :: *`, like `[a]`.</div><div><br></div><div>Thanks,</div><div>Will</div><div><br></div></div>