[Agda] parameterized modules?

Andreas Abel andreas.abel at ifi.lmu.de
Wed Oct 17 14:18:51 CEST 2012

On 17.10.2012 12:42, Serge D. Mechveliani wrote:
> On Wed, Oct 17, 2012 at 08:36:28AM +0200, Andreas Abel wrote:
>> On 15 Oct 2012, at 7:09 PM, Serge D. Mechveliani wrote:
> [..]
>>> are you sure that Agda really needs parameterized modules?
>>> For example, Haskell has not such and still looks all right
>> It looks alright, but you cannot really do abstract developments.  For
>> the other end of the spectrum of module systems, see ML functors.
>>> (except absence of dependent types).
>>> If they are replaced with classes and instances by records, then the
>>> implementors could save effort.
>> Classes cannot replace modules, since classes are inferred automatically
>> and thus need unique instances.
> Sorry, this is somewhat not so clear to me, looks rather generic.
> Consider an example of a parametrized module for several functions
> related to sorting a list:
>   module Sort (A : Set) (_<=_ : Rel A _)
>                         (isDTO : IsDecidableTotalOrder \equiv _<=_)
>     where
>     insert : A -> List A -> List A
>     insert x []       = x :: []
>     insert x (y :: ys)  with x <=? y
>     ...               | yes _  = x :: y :: ys
>     ...               | no _   = y :: insert x ys
>     <other related functions>
> (the examples in this letter were not tried to compile).
> I understand its idea as follows.
> module Sort-T-l = Sort T lessEQ
> produces a module  Sort-T-l  which is ready to perform `insert' for
> for this given particular type T and this given DTO ordering  lessEq  on
> T  (T and lessEq  are uniformly substituted for  A and _<=_).
> And then, a programmer can choose different pairs (T , lessEq).
> Now I try to replace a parameterized module with using classes:
>    insert : {A : Set} -> {_<=_ : Rel A _} ->
>             (isDTO : IsDecidableTotalOrder \equiv _<=_) -> A -> [A] -> [A]
>    open IsDecidableTotalOrder {{...}}
>    insert _     x []         =  x :: []
>    insert isDTO x (y :: xs)  with x <=? y
>    ...               | true  = x :: y :: ys
>    ...               | false = y :: insert isDTO x ys
> Now, having any given  T : Set,  any given  lessEq : Rel T _,
> and a record value
>                     isDTO : IsDecidableTotalOrder \equiv lessEq
> for this lessEq,
> a call             insert isDTO x xs
> performs the insertion for any  x : T,  xs :: List T.
> Fetching to `insert' different pairs (T , lessEq) will do the needed
> thing.
> The effect is the same as in a parameterized module.
> Is not it?
> If it is the same, why does one need a parameterized module?
> I see only the following reason.
> Suppose that the above parameterized module  Sort  has many types and
> functions:  insert, sort, merge, merge-sort ...,
> and they depend on the _same_ above parameters  (A, _<=_, isDTO).
> A parameterized module allows to _skip uniformly_ the part
>    (A : Set) (_<=_ : Rel A _) (isDTO : IsDecidableTotalOrder \equiv _<=_)
> in all these item declarations
> (no matter whether they are denoted as implicit by `{}').
> Now, I think that:
> a parameterized module is a tool for an automatic insertion of some
> common declaration prefix to many declarations in this module.
> Is it for something else?

That is already the main purpose.

Internally, we use parametrized as a tool for local definitions, like 
where clauses.

> Well, this may be a reason for supporting parameterized modules.
>> Classes cannot replace modules, since classes are inferred automatically
>> and thus need unique instances.
> Can you illustrate this on the above sorting example?
> In the above my example,   IsDecidableTotalOrder  stands for something
> like a  class,  and each value pair  (lessEq, isDTO)  stands for an
> instance of this class.
> Right?
> Where is an automatic class inference, where is an unique instance?

Well, you have not turned module Sort into a class.

You have just abstracted over the Sort module parameters manually in 
insert.  Parametrized modules do that for you.

> A programmer has a choice:
> (PM) to program the sorting-related functions by using a parameterized
>       module, as in the first example,
> (C) instead of using a parameterized module to use the class denotations
>      in each sorting-related function (as in the second example).
> (C) replaces (PM) at the cost of inserting a repeating prefix in the
>      declarations in each related function.
> And I suspect that choosing (PM) one looses a certain imporant
> possibility as compared with (C).
> This will be visible in the case when sorting is lifted to a tower
> of types built by repeated applying of several type constructors
> (for example, the tower over the set {Nat, \times, List}).
> This year I had such an unlucky experience with  parsing  designed via
> parameterized modules  as compared with its design via  classes.
> This was with the  Spad  language which has _categories_ for classes
> and _packages_ for parameterized modules.
>  From this time, I a bit fear of parameterized modules, have an
> impression that they tend to lead to a wrong field.

Modules are not first-class in Agda.  If you would need to abstract over 
modules or compose modules, then switch to records, which are 
first-class.  Classes are just records used with instance inference.

Note that records do not support recursive function declarations, for 
instance, nor local data type definitions.


Andreas Abel  <><      Du bist der geliebte Mensch.

Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY

andreas.abel at ifi.lmu.de

More information about the Agda mailing list