You should seq or use a bangpattern on the arguments before taking the stable names to ensure that the result is reproducible if the input thunks may later be forced.
> let y = 1 + 1; x = id y in (ptrEqual x y, x `seq` y `seq` ptrEqual x y)
(False,True)
a === b = a `seq` b `seq` unsafePerformIO $ (==) <$> makeStableName a <*> makeStableName b
> let y = 1 + 1; x = id y in (x === y, x `seq` y `seq` x === y)
(True,True)
This may be less of a problem if your tree has bang patterns, but even there it it sometimes easy to trip up and make a mistake with the unforced root of a tree.
-Edward Kmett
On Wed, 2010-03-03 at 18:58 +0100, Axel Simon wrote:Safe but not pure?
> On 03.03.2010, at 17:30, Milan Straka wrote:
>
> > Any easy way of comparing pointers? I mean, if I have something like
> > Tree a = N | B (Tree a) a (Tree a)
> > and have (l::Tree a) and (r::Tree a), can I ask about the "physical
> > equality"?
>
> You can! Despite the names appearing in the following code, the
> following is safe:
>
> -- | Equality on pointers.
> ptrEqual :: a -> a -> Bool
> ptrEqual x y = unsafePerformIO $ do
> nx <- makeStableName x
> ny <- makeStableName y
> return (nx==ny)
jcc
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries