I'm attempting to write a thin wrapper around repa to provide extra constraints for some domain-specific work I'm doing. I have the type:
newtype Tile p r a = Tile { _array :: Array r DIM2 a }
where Array
comes from repa
. I'd like to hide the r
because it adds noise to type signatures and makes Tile
a leaky abstraction:
newtype Tile p a = Tile { _array :: Array ? DIM2 a } -- what should `?` be?
Unfortunately, that r
can change between repa operations. Most of the time it's D
(for "delayed representation"), but when the data is first created from a list or vector it would be U
("unboxed vector") or V
("boxed vector"). These are used as type hints to help repa optimize its operations.
Is there a way for me to hide the r
as I'd like, but allow it to vary naturally internally without affecting typechecking with my wrapper Tile
type? Is this the domain of RankNTypes
and friends? I'll admit I don't understand them very well. To be the most clear, I'd like to be able to write:
foo :: Tile p a -> Tile p b -> Tile p c
where the two Tile
arguments contain (for instance) an Array U DIM2 Int
and Array D DIM2 Int
respectively. Is this a bad thing to desire?