[m-users.] Typeclasses

Dirk Ziegemeyer dirk at ziegemeyer.de
Sun Oct 15 06:39:30 AEDT 2017


Hi,

> Am 14.10.2017 um 16:56 schrieb Julien Fischer <jfischer at opturion.com>:
> 
> 
> Hi all,
> 
> On Sat, 14 Oct 2017, Tomas By wrote:
> 
>> On 2017-10-14 14:44, Mark Brown wrote:
>>> On Sat, Oct 14, 2017 at 11:00 PM, Dirk Ziegemeyer <dirk at ziegemeyer.de>
>>> wrote:
>>>> Is it possible at all to define a typeclass key_value_store with the
>>>> method search_value and then to declare map as an instance of this
>>>> typeclass?
>>> 
>>> No, "map" is a constructor, not a type, so you would need a
>>> constructor class not a typeclass.
>> 
>> 
>> Isn't it both?
>> 
>> This is the closest I can get to Dirk's example:
>> 
>> 
>> :- type store ---> store(map(int,int)).
>> 
>> :- typeclass key_value_store(S) where [
>>  pred search_value(S::in,int::in,int::out) is semidet
>> ] .
>> 
>> :- instance key_value_store(store) where [
>>  pred(search_value/3) is my_map_search
>> ] .
>> 
>> :- pred my_map_search(store::in,int::in,int::out) is semidet.
>> my_map_search(store(Map),K,V) :- map.search(Map,K,V).
> 
> I think we can do a little better than that:
> 
> First of all, if we define:
> 
>    :- typeclass key_value_store(Store, K, V) <= (Store -> K, V) where [
>        pred search_value(Store::in, K::in, V::out) is semidet
>    ].
> 
> then:
> 
>    :- type key(K) ---> key(K).
>    :- type value(V) ---> value(V).
> 
> The instance for maps then looks like:
> 
>    :- instance key_value_store(map(K, V), key(K), value(V)) where [
>        ( search_value(Map, key(Key), value(Value)) :-
>            map.search(Map, Key, Value)
>        )
>    ].
> 
> One for red-black tree looks like:
> 
>   :- instance key_value_store(rbtree(K, V), key(K), value(V)) where [
>      ( search_value(RBTree, key(Key), value(Value)) :-
>          rbtree.search(RBTree, Key, Value)
>      )
>   ].
> 
> The wrapper types key/1 and value/1 are a bit ugly, but the restrictions
> Mercury currently places upon instance heads require them.

Thank you for the tip with the wrapper types to conform to Mercury's requirement that a type in an instance declaration must be either a type with no arguments or a polymorphic type whose arguments are all type variables.

My original piece of code looked very similar to Thomas’ example and didn’t compile because I used an equivalence type in the instance declaration:
:- type store == map(int,int).

It compiles now with the wrapper type:
:- type store ---> store(map(int,int)).

Dirk.



More information about the users mailing list