[mercury-users] Present state of type classes - especially for parametrized types
Jörg Roman Rudnick
joerg.rudnick at t-online.de
Wed Oct 4 13:43:01 AEST 2006
Dear Ralph,
the pseudo-program, fringe.m, was attached to my last mail.
Maybe it was not readable - here in plain text, again:
%%% snip %%%%%%%%%%%%%%%%%
:-module fringe.
:-interface.
:-import_module io.
:-pred main(io::di, io::uo) is det.
:-typeclass fringe(Q) where
[
pred empty(Q::in) is semidet,
func tail(Q)= Q,
%func insert(T, Q)= Q <= node(T),
func first(Q)= T <= node(T)
].
:-typeclass node(NodeT) where
[
pred show(NodeT::in, io::di, io::uo) is det
].
%%===============================================
:-implementation.
:-import_module list, queue, exception.
:-instance fringe(queue(T)) <= node(T) where
[
pred(empty/1) is queue.is_empty,
func(tail/1) is q_tail,
%func(insert/2) is q_insert,
func(first/1) is first
].
:-instance node(int) where
[
pred(show/3) is io.write_int
].
:-func q_insert(T, queue(T))= queue(T) <= node(T).
q_insert(Dink, Queue)= queue.put(Queue, Dink).
:-func q_tail(queue(T))= queue(T).
q_tail(Queue)= Tail :-
(if queue.get(Queue, _F, T) then Tail = T
else throw("! empty fringe...")).
:-func q_first(queue(T))= T <= node(T).
q_first(Queue)= First :-
(if queue.first(Queue, F) then First = F
else throw("! empty fringe...")).
:-func first2(queue(T))= T <= node(T).
first2(Q)= first(Q).
main(!IO) :-
Q0 = queue.delete_all(queue.list_to_queue([1]), 1),
Q2 = queue.list_to_queue([2,3]),
(if empty(Q0) then write_string("Q0 is empty\n", !IO)
else write_string("Q0 isn't empty\n", !IO)),
(if empty(Q2) then write_string("Q2 is empty\n", !IO)
else write_string("Q2 isn't empty\n", !IO)),
write_string("tail of Q2: ", !IO),
Tail = tail(Q2),
write(Tail, !IO),
nl(!IO),
write_string("first of Q2: ", !IO),
%_First = first2(Q2),
%show(First, !IO),
nl(!IO).
%%% snap %%%%%%%%%%%%%%%%%
The compiler messages are, as told, of )o+>0.13.
>
>> (1) 'O-tone R.B.':
>> > The empty/0 func causes us some grief, since it doesn't mention T;
>> instead
>> > we need to jump through a hoop like
>> > func empty(T) = S, % T is a dummy arg to make the types work
>> > mode empty(unused) = out is det,
>> > which isn't very satisfying.
>>
>
> Here you've omitted the context, which was a discussion of
> type classes for collections, where there is a collection type and an
> item type. Functional dependencies now handle the empty/0 situation.
>
Hey, 'type classes for collections' totally hits my point... ;-)
If you say 'empty/0', (i.e., func constant= T::out) is possible now,
that is more than I would wish for... :-)
>> (2) 'O-tone R.B.' (others discussed similar ideas in the following):
>> > But things get worse: in an instance declaration the parameters must
>> all be of the form
>> > `typename(typevar, ...)', and not just `typevar', which
>> > rules out
>> > :- instance sequence(list(T), T).
>> > Oh deary me! What is needed, as was discussed at the end of last
>> year,
>> > is the ability to handle constructor classes, so we could write
>> > :- typeclass sequence(S(T)) where [
>> > func empty = S(T),
>> > func cons(T, S(T)) = S(T),
>> > func head(S(T)) = T,
>> > func tail(S(T)) = S(T),
>> > ...
>> > ].
>> > and
>> > :- instance sequence(list(T)).
>>
>
> Again, functional dependencies can handle many of these cases.
> Constructor classes would be even better, but right now adding them is
> not a priority.
>
>
I have got 'empty/1' (check pred) and 'tail/1' running - you already
told the same about 'empty/0'... since we are speaking about applying
functional dependencies, you don't mean I can dare to expect 'cons/2'
and 'head/1' are also possible, do you??
>> (b) Without a such lore, the compiler seems not to be able to read it
>> from the instance declaration (which in fact contains it) - moreover
>> it seems to be more serious than just a 'typecast' issue - wrapping a
>> typeclass call in an appropriate function lets the compiler finish
>> successfully, but seems to produce an endless loop at execution:
>> In the attached example code, this loop already happens when
>> uncommenting '% _First = first2(Q2),'.
>>
>
> I don't understand. If you can produce a short program containing the
> problem, that would be good.
>
I understand... you need 'fringe.m'...
>
>> Under the bottom line, I guess what I am trying to achieve is finding
>> a 'crude way' of having rank two polymorphism with )o+>0.13.
>>
>
> Now you've completely lost me! I still don't understand what
> it is you're trying to achieve. If you can produce a short
> pseudo-program illustrating what you want to do, that would help.
>
Of course, I will not hesitate to stop looking for 'a crude way', if not
necessary... :-)
I am very excited for your reply...,
Nick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20061004/ab1e838f/attachment.html>
More information about the users
mailing list