What is the precise promise/guarantee the Haskell language provides with respect to referential transparency? At least the Haskell report does not mention this notion.
Consider the expression
(7^7^7`mod`5`mod`2)
And I want to know whether or not this expression is 1. For my safety, I will do perform this twice:
( (7^7^7`mod`5`mod`2)==1, [False,True]!!(7^7^7`mod`5`mod`2) )
which now gives (True,False)
with GHCi 7.4.1.
Evidently, this expression is now referentially opaque. How can I tell whether or not a program is subject to such behavior? I can inundate the program with ::
all over but that does not make it very readable. Is there any other class of Haskell programs in between that I miss? That is between a fully annotated and an unannotated one?
(Apart from the only somewhat related question I found on SO there must be something else on this)
The problem is overloading, which does indeed sort of violate referential transparency. You have no idea what something like
(+)
does in Haskell; it depends on the type.When a numeric type is unconstrained in a Haskell program the compiler uses type defaulting to pick some suitable type. This is for convenience, and usually doesn't lead to any surprises. But in this case it did lead to a surprise. In ghc you can use
-fwarn-type-defaults
to see when the compiler has used defaulting to pick a type for you. You can also add the linedefault ()
to your module to stop all defaulting.