In the HLearn library that I'm working on, I have some container data type that looks like this:
data (Model params model) => Container' params model = Container'
{ baseparams :: params
, basemodel :: model
}
The problem is that this type is awkward to use because params
and model
are both uniquely determined from each other:
class Model params model | params -> model, model -> params
So it would be much more convenient if I didn't have to specify both of them when specifying the type. The compiler should be able to do it for me automatically.
My idea to solve this problem was to create a type alias that uses existential quantification:
type Container model = forall params . (Model params model) => Container' params model
But this doesn't work. If I make a Container'
instance like normal, everything works fine:
data ContainerParams params = ContainerParams params
instance (Model params model) => Model (ContainerParams params) (Container' params model)
But when I use my Container
type:
instance (Model params model) => Model (ContainerParams params) (Container model)
ghc explodes:
Illegal polymorphic or qualified type: Container model In the instance declaration for `Model (ContainerParams params) (Container model)'
I have no idea what this error message means. Is it possible to fix my solution somehow to make a Container
type where you don't have to specify the params?
Edit: I should note that moving the forall
statement into the Container'
declaration seems to require a bunch of unsafeCoerce
s, so that seems like a bad solution.
Also, I could change the type Container
into data Container
and get things to work, but this requires I redeclare all instances that Conatiner'
is part of, and I don't want to do that. I have many different types that follow this pattern, and so it seems like there should be a generic way to solve this problem.