[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