Reputation: 699
Ok, I'm attempting to make a function to determine if a list of tuples is transitive, i.e. if (x,y) and (y,z) is in the list, then (x,z) is also in the list.
For example, [(1,2), (2,3), (1,3)]
is transitive.
Now, coming from a Prolog background, the following makes sense to me:
transitive xs = and [elem (x, z) xs | (x, y) <- xs , (y, z) <- xs ]
HOWEVER, it doesn't work. It appears that the 'y' does not get the single value as I would expect, but is 'reassigned' when it comes to the second tuple. Instead, we must use:
transitive xs = and [elem (x, z) xs | (x, y1) <- xs , (y2, z) <- xs, y1 == y2 ]
Why is this so? Why does the first example not cause an error, and doesn't this go against functional programming languages' principle of 'referential transparency?'
"However, in pure functional and logic languages, variables are bound to expressions and keep a single value during their entire lifetime due to the requirements of referential transparency." - Wikipedia
Thanks!
Upvotes: 6
Views: 234
Reputation: 183873
Even in functional languages, there is name shadowing. Sometimes that is useful.
In the first code, the (y,z) <- xs
shadows the y
bound by the (x,y) <- xs
before.
Compile with warnings turned on to be alerted of such things.
Upvotes: 8