[Haskell-cafe] Library for overloaded indexing (a la (!))

William Yager will.yager at gmail.com
Thu Aug 13 05:18:09 UTC 2015

Hello all,

I put together a small library for the purpose of creating overloaded
indexing operators. The library is available at
https://hackage.haskell.org/package/keyed .

I would like to solicit some advice on the design of this library.

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).

I originally did this using MultiParamTypeClasses and
FunctionalDependencies, but thought this was cleaner; are there any good
reasons to go back to using FunDeps?

Data.Keyed provides pure indexing, while Data.MKeyed provides monadic
indexing (e.g. for mutable vectors or concurrent STM-based maps).

I'm having some trouble with the fact that mutable vectors are keyed on the
PrimState of their corresponding PrimMonad.

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.

(!) :: MKeyed d => d -> MKey d -> MContainer d (MValue d)
(!) :: IOVector a -> Int -> IO a
(!) :: STVector s a -> Int -> ST s a

Unfortunately, this causes an overlap (because both IOVector and STVector
are aliased to MVector).

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

instance (PrimMonad m, s ~ PrimState m) => MKeyed (MVector s a) where ...
    type MContainer (MVector (PrimState m) a) = m

because you can't have type synonyms on the LHS of the type.

I tried bringing `m` into scope using RankNTypes, but that didn't work.

Is there some syntax I can use to bring `m` into scope here?

Or should I be doing this part entirely differently?

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]`.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20150812/e8278fc0/attachment-0001.html>

More information about the Haskell-Cafe mailing list