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?