[mercury-users] typeclasses vs. univ and higher order programming

obo at ruk.cuni.cz obo at ruk.cuni.cz
Mon Oct 4 20:01:52 AEST 2004


Hello.

I'd like to create a list (or custom list-like type) of values and 
operators on them of various types.

:- type aggrslices --->
        nil
      ; some [T] cons(T, aggrslices).
:- type aggrslice(T) ---> aggrslice(
      column :: int,
      val    :: T,
      folder :: (func(T, T) = T),
      dumper :: (func(T) = string)
    ).

Then, I'd like to a have a simple "configuration" predicate to define 
handling of those various types.

:- type aggr --->
           min
         ; max
         ; collect
         % ...
         .

%               identifier, initer, aggregator, dumper
:- some [T] pred aggregator(
                    aggr,
                    (func) = T,
                    func(string, T) = T,
                    func(T) = string
    ).
:- mode aggregator(in, out, out, out) is det.

However, I fail to encode the initialization part properly:

   Aggr = min,
   InAggrs = nil,
   aggregator(Aggr, Initer, Folder, Dumper),
   AggrSlice = aggrslice(Column, Initer, Folder, Dumper),
   OutAggrs = cons(AggrSlice, InAggrs)
   % ...

grp.m:343: In clause for function `grp.new_mem/3':
grp.m:343:   in unification of variable `AggrSlice'
grp.m:343:   and term `aggrslice(Column, Initer, Folder, Dumper)':
grp.m:343:   type error in argument(s) of functor `aggrslice/4'.
grp.m:343:   Argument 2 (Initer) has type `(some [T] ((func) = T))',
grp.m:343:   expected type was `T';
grp.m:343:   argument 3 (Folder) has type `(some [T] (func(string, T) = T))',
grp.m:343:   expected type was `(func(T, T) = T)';
grp.m:343:   argument 4 (Dumper) has type `(some [T] ((func T) = string))',
grp.m:343:   expected type was `((func T) = string)'.

The Mercury Language reference gives a hint to use the type 'univ' if a 
predicate is expected to return values of different types at different 
calls. However, I need the predicate to return different higher-order 
types, and I do not know, how to write this.

Theoretically, exactly this behavior could be achieved with type classes, 
plain list of elements of type X, where X is aggregable, i.e. where I 
define how to fold and dump values of X. The problem with type classes is 
that I often need to use *different* handles for the *same* type. (Such as 
performing minimum and maximum functions, both on ints.)

The vanilla way of instantiating type classes doesn't allow for this:

:- instance aggregable(int) where [
    ...
    ].

I do not like to wrap all needed types with a fake type constructor:

:- instance aggregable(int_for_max) where ...
:- instance aggregable(int_for_min) where ...
:- type int_for_max ---> int_for_max(int).
...

Is this kind of wrapping the only way, or can I somehow emloy the 'univ' 
and my higher order predicates?

Thanks, O.

--
Ondrej Bojar (mailto:obo at cuni.cz)
http://www.cuni.cz/~obo

--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list