[clean-list] unique record fields.
Martijn Vervoort
martijnv@cs.kun.nl
Wed, 6 Jun 2001 08:57:34 +0200
Hello,
> Hello,
>
> > Hello,
> >
> > This is probably a very basic question (for which I apologize).
>
> Unfortunately, it is not such a basic question.
>
> > I am trying
> > to write hashtables in Clean. The way I want to go about it is to
> define
> > a Map type (parameterized by key and value types) corresponding to a
> record
> > containing a (unique) array (and some other useful state):
> >
> > :: *Map *a b =
> > { state :: {[(a, b)]}
> > , size :: Int
> > , put :: (Map a b) -> a -> b -> (Map a b)
> > ... etc.
> > }
> >
> > Then the function to construct an object of this type would look like:
> >
> > Map hash equal size =
> > { state = createArray size [] // <- error 2
> > , put = put
> > ... etc.
> > }
> > where
> > put :: (*Map *a b) *a b -> (*Map *a b) // <- error 1
> > put map key val =
> > ...
> > map
> >
> > However when I try to compile this program I get the following type
> errors:
> >
> > Type error [Map.icl,34,put]: "map" attribute at the indicated position
> cannot be coerced: Map ^ a b | == b
> > Type error [Map.icl,22,Map]: "createArray ({})" cannot create a
non-unique
> variant of this type at the indicated position: ^ [(a,b)]
> >
>
> Error 2: You are in effect constructing an array of unique elements (due
to
> the '*' in front of a in the type definition of Map).
> But if you take a look at the type of createArray you'll see:
>
> createArray :: !Int e -> .(a e)
>
> Because there is no '.' or '*' in front of e, createArray can
only
> be used
> to create arrays of *non-unique* elements.
>
> Solution: I always use array-comprehensions to construct such
> arrays:
>
> state = {[] \\ i <- [1..size]}
>
> This will do the trick.
>
> Error 1: There are actually two errors here. The first I won't even try
to
> explain.
> (because I can't) You have to replace the type of 'put' in your
If the put-function is partially applied, it becomes necessarily unique
which
means that the partially applied put-function *itself* becomes unique to
prevent sharing of its second and third argument unique object.
The language report version 1.3, page 62/63 under Higher Order Uniqueness
Typing describes it also.
> record by:
>
> put :: (Map a b) -> *(a -> *(b -> (Map a b)))
>
> It still is obscure to me why this is needed.
> Secondly, you have to change the type of the local function
'put'.
> This one is easier: the '*' annotation always has to be written
> *outside*
> the brackets, not inside. So:
>
> put :: *(Map *a b) *a b -> *Map *a b
>
> (The * inside the brackets will be ignored by the parser and can
> be omitted)
>
> As you can see, there are quite some things going on here.
>
> > I am doing nothing in the program except defining the constructor, I
am
> not
> > even calling it. Does anyone have any insight into this?
> > If this list is not the right place for these sorts of questions I
would
> be
> > happy to direct them to the right place.
> >
> > Thanks in advance,
> >
> > Ilya
> >
>
> Maarten de Mol
Martijn Vervoort
>
> PS: Note that fields in a unique record will not automatically be unique
> themselves.
> If you want the state field to be unique, you have to write
>
> state :: *{[(a,b)]}