Transparent implementation of a specific form of dynamic typing

The main idea is that I have a number of functions that work with any types from a certain class, but at runtime the program should read the configuration file and extract an element of one of the types in the class.

For example, I have a class "Coefficient", its various instances and functions of different types that are polymorphic over the types of this class; at run time, you need to determine the specific type of this class and pass it.


I am not sure how to solve this correctly; I tried to compose “complex” types, doing something like:

data CompoundCoeff = CompoundInt Int | CompoundDouble Double | ... 

where Int, Double, ... are instances of the Coefficient class.
Nevertheless, he began to make great efforts to adapt all the functions involved in the code to work with these composite types (and this is not a good solution, really). It would be nice if all functions had the same, light type, for example.

 Coefficient a => a -> (stuff not involving a anymore) 

but unfortunately this is not so.

Another problem that I am facing is that I am using type families and have something like

 class (Monoid (ColourData c), Coordinate (InputData c)) => ColourScheme c where type ColourData c :: * type InputData c :: * colouriseData :: c -> (ColourData c) -> AlphaColour Double processInput :: c -> InputData c -> ColourData c 

This does not go clean if I need to use some sort of ColourData composite data type, like the previous one; in particular, I can no longer guarantee that the data stream gives a consistent type (and not just different "subtypes" of a complex type) and, among other things, would have to be a dummy Monoid instance if I were to create a composite ColourData type.

I also studied Data.Dynamic, but again I don’t see how it will solve problems correctly; it seems the same problems seem to be (well, even worse, given that there is only one “common” dynamic type, as I understand it).


Question:. How can I implement dynamic data types subordinate to specific classes without having to rewrite all the functions associated with these data types? It would be better if I did not have to sacrifice any security, but I am not too optimistic.
The program must read the configuration file at run time, and all necessary functions polymorphic over the corresponding class must be applied.

+7
source share
2 answers

The traditional way of providing an object that guarantees that it is an instance of typeclass Foo , but does not provide any additional guarantees, looks like this:

  {-# LANGUAGE ExistentialTypes #-} data SomeFoo = forall a . Foo a => SomeFoo a instance Foo SomeFoo where -- all operations just unwrap the SomeFoo straightforwardly 

or using GADT, which may be more readable ...

  data SomeFoo where SomeFoo :: Foo a => a -> SomeFoo 
+7
source

One suggestion would be to write one top-level function that does all the finishing touches after you select a type:

 topLevel :: SomeTypeClass a => a -> IO () 

Then your program could be written something like this:

 main = do config <- readConfig case config of UseDouble n -> topLevel n UseSymbolic x -> topLevel x UseWidgetFrobnosticator wf -> topLevel wf 
+6
source

All Articles