[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