
Claus Reinke wrote:
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'.
However there is nothing in the functions themselves that restricts their use to just T Double. Thus the functions can be compared for equality by supplying an argument of type T Double but used elsewhere in the program with args of type (plain) Double eg: -- Change to module AbsNum instance (Simplify a)=>Eq (T a) where (==) (Const x) (Const y) = x == y (==) (Var x) (Var y) = x == y (==) (Add xs) (Add ys) = and (map (\(x, y) -> x==y) (zip xs ys)) (==) _ _ = False -- Not needed for the example module Main where import AbsNum f x = x + 2.0 g x = x + 1.0 + 1.0 funeq :: (T Double -> T Double) -> (T Double -> T Double) -> Bool funeq p q = let y = Var "y" in p y == q y main = do print (funeq f g) print (f 10) print (g 10) putStrLn "" print (funeq f f) print (f 10) print (g 10)
main False 12.0 12.0
True 12.0 12.0 Thus we can determine that f is implemented by different code from g (The example would be even more convincing if Int's were used instead of Double's) and so f and g are not interchangeable.
... nothing prevents us from defining that instance in such a way that we construct a representaton instead of doing any additions.
Thus referential transparency of polymorphic functions is foiled. Regards, Brian.