
import AbsNum
f x = x + 2 g x = x + 1 + 1
y :: T Double y = Var "y"
main = do print (f y) print (g y)
...which results in...
*Main> main (Var "y")+(Const (2.0)) (Var "y")+(Const (1.0))+(Const (1.0))
...is this competely unrelated?
Interesting! Referential transparency (as I understand it) has indeed been violated. Perhaps the interaction of GADTs and type classes was not sufficiently studied before being introduced to the language.
So I'm now just as puzzled as you.
the usual way to achieve this uses the overloading of Nums in Haskell: when you write '1' or '1+2', the meaning of those expressions depends on their types. in particular, the example above uses 'T Double', not just 'Double'. recall the problem (simplified): mapping from values to representations is not a function (unless we pick a unique representative for each class of equivalent expressions). but there is nothing keeping us from going the other way: from representations to values. the example above is even simpler, as it only constructs representations. what the overloading for representation trick usually does is to create an instance of Num for representations of arithmetic expressions.when you write '1+2::Representation', that uses 'fromInteger' and '+' from the Num instance for the type 'Representation', and nothing prevents us from defining that instance in such a way that we construct a representaton instead of doing any additions. cheers, claus ps. that AbsNum module seems to do a lot more besides this, but search for the Num instance. a simpler example module, just pairing representations with values, can be found here: http://www.cs.kent.ac.uk/people/staff/cr3/toolbox/haskell/R.hs