[Haskell-cafe] Suggestions for simulating Object ID

Ryan Ingram ryani.spam at gmail.com
Tue Jun 30 12:44:36 EDT 2009


On Tue, Jun 30, 2009 at 9:16 AM, Felipe Lessa<felipe.lessa at gmail.com> wrote:
> On Tue, Jun 30, 2009 at 07:57:07PM +0530, Hemanth Kapila wrote:
>> Can't we come up with something like this staying within the
>> limits of purity?
>
> No, because that would break referential transparency :(.  I.e.,
> it would be possible to distinguish things that should be
> "equal", such as '3' from '1+2'.

This isn't entirely true; you can do something like this:

> newtype Unique = U Integer deriving (Eq)
> newtype UniqueM a = UniqueM (State Integer a) deriving Monad
> runUniqueM (UniqueM a) = evalState a 0

> newUnique = UniqueM $ do
>    u <- get
>    put $! (u+1)
>    return (U u)

Also, if you are willing to go inside of IO/ST for some bits of your
code, you can use some tricks with unsafeInterleaveIO/ST to create
data structures with unique ids that only get created if they are
used; this allows creating infinite data structures and still keeping
object ID.  The returned data structure is still pure if the "U"
constructor is hidden; all we can do is compare uniques for equality.
You can relax this slightly by adding an Ord derivation; this
technically allows you to observe creation order for the uniques which
is wrong, but it's quite useful to be able to use Uniques as map keys.

> data Tree a = Tree a (Tree a) (Tree a)
> infTree :: IO (Tree Unique)
> infTree = do
>    r <- newIORef 0
>    mkTree r
> mkTree :: IORef Integer -> IO (Tree Unique)
> mkTree r = unsafeInterleaveIO $ do
>     v <- readIORef r
>     writeIORef r $! (v+1)
>     l <- mkTree r
>     r <- mkTree r
>     return (Tree (U v) l r)

I believe GHC uses this technique internally.

  -- ryan


More information about the Haskell-Cafe mailing list