[clean-list] Updating unique structures in unique structures in unique structures

John van Groningen johnvg at cs.ru.nl
Wed May 7 17:18:12 MEST 2008


Norbert Zeh wrote:
>When I first got to know Clean, I came from the Haskell side and was impressed that Clean had found a way to make array updates efficient while maintaining referential transparency.  Now I've run into my first round of problems with unique objects, and I'd appreciate some help.  Here's what I want to do.  I want to define a record type one of whose fields is an array, and I want to be able to update the array.  So the array has to be unique and, therefore, the record type has to be unique:
>
>:: *A = { id :: Int
>        , a  :: *{Int}
>        }
>
>In a unique array of unique arrays, I could use the replace function to get a unique reference to one of the arrays stored in the outer array.  My question is:  Is there a similar way to get a unique reference to the elements of a record?

A unique element of a record can be updated by selecting and updating
the element in the same function. For example:

f r = {r & a = some_update_function r.a}

However because of limitations in the implementation of the reference analysis
of uniqueness typing, a unique element cannot be selected using a ! selection
and cannot be updated using a nested update.

So to select a unique element use a pattern match or a . selection.
For example use:

f r=:{a}
    = {r & a = some_update_function a}

f r
    # {a} = r
    = {r & a = some_update_function a}

f r
    # a = r.a
    = {r & a = some_update_function r}

But not:

f r
    # (a,r) = r!a
    = {r & a = some_update_function a}

To update a unique element in another unique element use for example:

f r=:{v1=v1=:{v2}}
    = {r & v1 = {v1 & v2 = some_update_function v2}}

f r
    # {v1=v1=:{v2}} = r
    = {r & v1 = {v1 & v2 = some_update_function v2}}

f r=:{v1}
    = {r & v1 = {v1 & v2 = some_update_function v1.v2}}

f r
    # {v1} = r
    = {r & v1 = {v1 & v2 = some_update_function v1.v2}}

f r
    # v1 = r.v1
    = {r & v1 = {v1 & v2 = some_update_function v1.v2}}

:: *R1 = {v1::R2}
:: *R2 = {v2::*{Int}}

But not:

f r
    = {r & v1.v2 = some_update_function r.v1.v2}}

>The reason why I'd like to do this is that I have a number of nested unique references of this type.  In particular, I have another record type:
>
>:: *B = { id :: Int
>        , a  :: *{A}
>        }
>
>So threading my way through the reference hierarchy makes for rather unreadable code, and I'd like to have a reference to the array inside an A-record to manipulate it and later patch it back into the A-record.

You can do this in the following way (I have renamed field 'a' of B to 'aa'):

f b i
    # (aai,aa) = replace b.aa i dummy_a
    # new_a = update_a aai.a
    = {b & aa = {aa & [i] = {aai & a = new_a}}}

:: *A = { id :: Int
        , a  :: *{Int}
        }

:: *B = { id :: Int
        , aa :: *{A}
        }

dummy_a :== {id=0,a={}}

update_a :: *{Int} -> *{Int}
update_a a = a


Kind regards,

John van Groningen


More information about the clean-list mailing list