Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transparently implementing a particular form of dynamic typing

The basic idea is that I have a range of functions that work on any types from a particular class, but at runtime the program is supposed to read a configuration file and extract an element of one of the types in the class.

For instance, I have a 'Coefficient' class, various instances of it, and functions of various types that are polymorphic over types of that class; at runtime one particular type of that class is to be determined, and passed around.


I'm unsure how to properly address this; I tried making up 'compound' types, doing something like:

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

where Int, Double, ... are instances of the class 'Coefficient'.
However, it started to become a big effort to adapt all the functions involved in the code to work with these compound types (and it's not a nice solution either, really). It would be OK if all functions had the same, easy type, e.g.

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

but that's unfortunately not the case.

Another issue I ran into, is that I'm 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 doesn't go through cleanly if I have to use some sort of compound ColourData datatype, 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 compound type), and would (among other things) have to make up a bogus Monoid instance if I did make up a compound ColourData type.

I've also looked into Data.Dynamic, but again I can't see how it would properly address the issues; the exact same problems seem to appear (well, slightly worse even, given that there is only one 'generic' Dynamic type as I understand it).


Question: How can I implement dynamic datatypes subordinate to particular classes, without having to rewrite all the functions involving those data types? It would be best if I didn't have to sacrifice any type safety, but I'm not too optimistic.
The program is supposed to read a configuration file at runtime, and all the requisite functions, polymorphic over the relevant class, are to be applied.

like image 932
Sam Derbyshire Avatar asked Apr 02 '12 16:04

Sam Derbyshire


People also ask

How is dynamic typing implemented?

The operations on these dynamic data types (add, subtract, compare) are usually implemented by a virtual method table, which is for each data type a number of pointers to functions that implement the desired functionality in a type-specific way.

What is dynamic typing example?

Dynamic typing means that the type of the variable is determined only during runtime. Due to strong typing, types need to be compatible with respect to the operand when performing operations. For example Python allows one to add an integer and a floating point number, but adding an integer to a string produces error.

What programming language that is dynamic in typing?

A language is dynamically-typed if the type of a variable is checked during run-time. Common examples of dynamically-typed languages includes JavaScript, Objective-C, PHP, Python, Ruby, Lisp, and Tcl.

Why is dynamic typing useful?

Advantages of dynamically-typed languages:The absence of a separate compilation step (which is much more common) means that you don't have to wait for the compiler to finish before you can test changes that you've made to your code. This makes the debug cycle much shorter and less cumbersome.


1 Answers

The traditional way to provide an object that guarantees that it is an instance of typeclass Foo, but makes no additional guarantees, is like so:

 {-# LANGUAGE ExistentialTypes #-}
 data SomeFoo = forall a . Foo a => SomeFoo a

 instance Foo SomeFoo where
   -- all operations just unwrap the SomeFoo straightforwardly

or, with GADTs, which might be more readable...

 data SomeFoo where
   SomeFoo :: Foo a => a -> SomeFoo
like image 76
Louis Wasserman Avatar answered Sep 21 '22 21:09

Louis Wasserman