[Agda] Recursive instance search

Ulf Norell ulf.norell at gmail.com
Fri Jul 11 20:32:11 CEST 2014


Awesome work. For now, I put it in a branch 'classes' in the main repo and
granted you commit rights. I will try it out on UlfNorell/agda-prelude,
which uses a lot of instance arguments.

/ Ulf


On Fri, Jul 11, 2014 at 12:26 PM, Guillaume Brunerie <
guillaume.brunerie at gmail.com> wrote:

> Hello all,
>
> As some of you know, I started working on recursive instance search
> during the previous AIM and the code is now available on my GitHub
> here : https://github.com/guillaumebrunerie/agda (should I open a pull
> request against the official Agda?)
>
> The main outstanding issue is that there is no termination check yet
> so if you’re not careful when defining your instances you can easily
> make Agda loop.
> Also, I haven’t really thought about namespace management, for
> instance 'hiding' does not hide instances (but serialization should
> work, though).
>
> I copy-pasted the relevant part of the CHANGELOG below (I borrowed
> part of the text in issue 938) and you can also look at the two files
> test/succeed/RecursiveInstanceSearch{,Level}.agda to see some more
> advanced examples of recursive instance search.
>
> Of course I welcome any feedback/bug reports.
>
> Cheers,
> Guillaume
>
>
>
>
> * Instance search is now more efficient and recursive (see issue 938)
>   (but without termination check yet)
>
>   A new keyword `instance' has been introduced (in the style of
>   `abstract' and  `private') which must now be used for every
>   definition/postulate that has to be taken into account during instance
>   resolution. For example:
>
>     {-# OPTIONS --copatterns #-}
>
>     record RawMonoid (A : Set) : Set where
>       field
>         nil  : A
>         _++_ : A -> A -> A
>     open RawMonoid
>
>     instance
>       rawMonoidList : {A : Set} -> RawMonoid (List A)
>       rawMonoidList = record { nil = []; _++_ = List._++_ }
>
>       -- using copatterns to define this recursive instance:
>
>       rawMonoidMaybe : {A : Set} {{m : RawMonoid A}} -> RawMonoid (Maybe A)
>       nil rawMonoidMaybe = nothing
>       _++_ rawMonoidMaybe nothing mb = mb
>       _++_ rawMonoidMaybe ma nothing = ma
>       _++_ (rawMonoidMaybe {{m}}) (just a) (just b) = just (_++_ m a b)
>
>   Moreover, each type of an instance must end in (something that reduces
>   to) a named type (e.g. a record, a datatype or a postulate). This
>   allows us to build a simple index structure
>
>     data/record name  -->  possible instances
>
>   that speeds up instance search.
>
>   Instance search takes into account all local bindings and all global
>   'instance' bindings and the search is recursive. For instance,
>   searching for
>
>     ? : RawMonoid (Maybe (List A))
>
>   will consider the candidates {rawMonoidList, rawMonoidMaybe}, fail to
>   unify the first one, succeeding with the second one
>
>     ? = rawMonoidMaybe {A = List A} {{m = ?m}} : RawMonoid (Maybe (List A))
>
>   and continue with goal
>
>     ?m : RawMonoid (List A)
>
>   This will then find
>
>     ?m = rawMonoidList {A = A}
>
>   and putting together we have the solution.
>
>   Be careful that there is no termination check for now, you can easily
>   make Agda loop by declaring the identity function as an instance. But
>   it shouldn’t be possible to make Agda loop by only declaring
>   structurally recursive instances (whatever that means).
>
>   Additionally:
>
>   * Uniqueness of instances is up to definitional equality (see issue 899)
>
>   * Instance search will not be attempted if there are unsolved metas in
>     the goal. The issue is that trying to typecheck [? ++ ?] would
>     generate a constraint of type `RawMonoid ?' to be solved by instance
>     search, but unification with `rawMonoidMaybe' will succeed and
>     generate a new constraint of type `RawMonoid ?2' to be solved by
>     instance search, and so on, so Agda would loop.
>
>     As a special case, if none of the instances declared for that type
>     is recursive, then instance search is attempted as usual even if
>     there are unsolved metas (no risk of looping here).
>
>   * Instances of the following form are allowed:
>
>         Π-level : {n : ℕ} {A : Set} {B : A → Set}
>                   {{_ : (a : A) → has-level n (B a)}}
>                   → has-level n ((a : A) → B a)
>
>       When searching recursively for an instance of type `(a : A) →
>       has-level n (B a)', a lambda will automatically be introduced and
>       instance search will search for something of type `has-level n (B
>       a)' in the context extended by `a : A'.
>
>   * There is no longer any attempt to solve irrelevant metas by instance
>     search
>
>   * Constructors of records and datatypes are automatically added to the
>     instance table
> _______________________________________________
> Agda mailing list
> Agda at lists.chalmers.se
> https://lists.chalmers.se/mailman/listinfo/agda
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.chalmers.se/pipermail/agda/attachments/20140711/44da357a/attachment.html


More information about the Agda mailing list