I assume the following problem can be solved using type arithmetic but haven't found the solution yet.
I have a finite map from strings to values (using Tries as implementation) that I parse from a binary/text file (json, xml, ...).
type Value = ... type Attributes = Data.Trie Value data Object = Object Attributes
Each map has the same type of values but not the same set of keys. I group maps with the same set of keys together to be able to prevent having to type-switch all the time I have a specialised function that requires certain keys:
data T1 data T2 ... data Object a where T1 :: Attributes -> Object T1 T2 :: Attributes -> Object T2 ...
This allows me to write something like:
f1 :: Object T1 -> ...
f1 :: Object -> f1 o | check_if_T1 o = ...
This works but has two disadvantages:
- Homogeneous lists of Object now become heterogeneous, i.e. I cannot have a list [Object] anymore.
I need to write a lot of boilerplate to get/set attributes:
get :: Object a -> Attributes get (T1 a) = a get (T2 a) = a ...
- Is there a better way to specialise functions depending on the constructor of an ADT?
How could I regain the ability to have a list [Object]? Is there a specialized version of Dynamic that only allows certain types? I thought about wrapping the Object again, but this would add a lot of boilerplate. For instance,
data TObject = TT1 T1 | TT2 T2 ...
What I need is:
get :: a -> TObject -> Object a
So that I can then derive:
collect :: a -> [TObject] -> [Object a]
I looked into HList but I don't think it fits my problem. Especially, since the order of types in [Object] is not known at compile time.
It sounds to me like this can be solved using functional dependency / type arithmetic but I simply haven't found a nice way yet.