Uniqueness annotations

Richard A. O'Keefe ok@atlas.otago.ac.nz
Mon, 1 Mar 1999 13:02:54 +1300 (NZDT)


I have a module that exports, amongst other things,

    :: RNG_State :== (!Int,!Int,!Int)

The intention is every random "thing" generator should have a type like

    foo :: <other parameters> !RNG_State -> *(<result>, RNG_State)

In particular, I have

    next_unit_random :: !RNG_State -> *(Real, RNG_State)

which returns a random number in the range [0.0,1.0) and an
updated state, and I have


    next_random_list :: !(!(RNG_State -> *(b,RNG_State))
                        !Int !RNG_State -> *(*[b], RNG_State)

which takes a random "b" generator, a number, and a random state,
and makes a new (unique) list of random "b"s, and returns that and
the updated random state.  That module gets through the Clean compiler
with no problems.

Next I want to use it to make random matrices, where a matrix is
represented by a list of lists.  I'd like Clean to know that the
whole matrix is new.  So I have

mrand :: !Int !Int !Real !Real !RNG_State -> *(*[*[Real]], RNG_State)
mrand m n l u s =
  next_random_list (next_random_list f n) m s
  where f :: !RNG_State -> *(Real, RNG_State)
        f s = (l + (u-l)*r, s`) where (r, s`) = next_unit_random s

From
    next_random_list :: !(!(RNG_State -> *(b,RNG_State))
                        !Int !RNG_State -> *(*[b], RNG_State)
    f ::                  !(RNG_State 0> *(Real,RNG_State))                        
    n ::                !Int
I expect
    (next_random_list f n) :: !RNG_State -> *(*[Real], RNG_State)
From
    next_random_list ::    !(!(RNG_State -> *(b,RNG_State))
                             !Int !RNG_State -> *(*[b], RNG_State)
    (next_random_list f n) :: !RNG_State -> *(*[Real], RNG_State)    
    m ::                     !Int
    s ::                          !RNG_State
I expect
    next_random_list (next_random_list f n) m s :: *(*[*[Real]], RNG_State)

But that's not what I get.  What I get is an error message.

    Type error [<file>,<line>,mrand]:
    "next_random_list" *attributed required but not offered
    at the indicated position: ([^ [Real]],RNG_State)

The <file>,<line> bit points to the line
  next_random_list (next_random_list f n) m s
and when I split it up, it appears to be the outer call to next_random_list
that's the problem, which is consistent with the error type.

To be perfectly honest, I didn't have the embedded declaration of f
originally, just the rule.  It all worked when I didn't have the
uniqueness annotations  If I change the type to

mrand :: !Int !Int !Real !Real !RNG_State -> *([[Real]], RNG_State)

I get no complaints from the compiler.

So what am I doing wrong?  I thought I *was* offering *[Real],
not [Real].  What should I do instead?