1

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?

Cactus
  • 27,075
  • 9
  • 69
  • 149
Colin Woodbury
  • 1,799
  • 2
  • 15
  • 25
  • You'll have to use an actual `data` declaration, but you can do `data Tile p a = forall d. Tile { _array :: Array d Dim2 a }`. – Alec Jun 28 '17 at 14:34
  • That's closer to what I need, yeah. But woops, turns out that `d` has some typeclass constraints elsewhere :S – Colin Woodbury Jun 28 '17 at 14:43
  • You can also put the constraints in the `data` declaration. `data Showable= forall a. Show a => SomeShow a`. – Alec Jun 28 '17 at 20:53

1 Answers1

1

I was able to get around the issue by forcing the wrapped Array to always contain the D type param by using the delay function.

This also allowed me to keep Tile as a newtype and also define a Functor instance for it.

Colin Woodbury
  • 1,799
  • 2
  • 15
  • 25