[Agda] overloading operations
Guillaume Allais
guillaume.allais at ens-lyon.org
Wed Nov 14 14:08:23 CET 2018
You don't need to add the prefix `Overloaded` anywhere: you can merely
import `Algebra` (without opening it) and give your new structures the
same names as the ones in the standard library. You can then refer to the
ones in `Algebra` by using qualified names e.g. `Algebra.Monoid`.
`instance` is a bit like instance in Haskell: everything declared in the
block is made available for instance resolution. The difference in Agda
is of course that you can also declare record values *outside* of instance
blocks. They are then *not* used by the automatic instance resolution.
But the user can have access to them like any other value.
By default the standard library does not declare anything as an `instance`.
If you want resolution to use some of the structures made available in the
stdlib, you will need to put all of these into an instance block like I did
in my example for Nat and Integer.
Cheers,
--
gallais
On 12/11/2018 19:05, Sergei Meshveliani wrote:
> On Sun, 2018-11-11 at 12:42 +0100, Guillaume Allais wrote:
>> Hi Sergei,
>>
>> Note that you don't the stdlib to change to be able to use Guillaume's
>> approach: you can add a layer on top of the stdlib giving a definition
>> of Semigroup exposing the Carrier and add a generic instance converting
>> from the stdlib's style to that new style. Self-contained example:
>>
>> ===================================================================
>> open import Level
>> open import Algebra
>> open import Algebra.Structures
>> open import Algebra.FunctionProperties.Core
>> open import Relation.Binary
>>
>> record OverloadedSemigroup {c} (Carrier : Set c) ℓ : Set (c ⊔ suc ℓ) where
>> infixl 7 _∙_
>> infix 4 _≈_
>> field
>> _≈_ : Rel Carrier ℓ
>> _∙_ : Op₂ Carrier
>> isSemigroup : IsSemigroup _≈_ _∙_
>>
>> instance
>> OS : ∀ {c ℓ} {{S : Semigroup c ℓ}} →
>> OverloadedSemigroup (Semigroup.Carrier S) ℓ
>> OS {{S}} = record { Semigroup S }
>>
>> import Data.Nat.Properties as NProp
>> import Data.Integer.Properties as ZProp
>>
>> instance
>>
>> *-ℕ : Semigroup _ _
>> *-ℕ = NProp.*-semigroup
>>
>> *-ℤ : Semigroup _ _
>> *-ℤ = record { isSemigroup = ZProp.*-isSemigroup }
>>
>> open import Data.Integer
>> open import Relation.Binary.PropositionalEquality
>>
>> open OverloadedSemigroup {{...}}
>>
>> abs-homomorphism : (m n : ℤ) → ∣ m ∙ n ∣ ≡ ∣ m ∣ ∙ ∣ n ∣
>> abs-homomorphism m n = {!!}
>> ===================================================================
>
> I thank both Guillaume-s for explanation.
>
> Suppose that one develops a library for operating with fractions and
> polynomials in general case. These functions will deal with various
> different instances of the structures of Setoid, Semigroup, Monoid,
> Group, ..., Semiring, CommutativeRing -- with different instances of
> their declared operations and relations (_≈_, _∙_, _+_; _*_ and such).
> Suppose that one needs to use in this library the same name for
> different used instances for each of this operations.
>
> I doubt of that this can be be totally supported.
> Also some program fragments are read easier if there are used different
> names.
>
> Still let us put that we need to use such an overloading wide enough.
> With your suggested approach, one needs to declare the `Overloaded'
> version for each of the structures
> Setoid, Semigroup, ..., Semiring, CommutativeRing.
> Then, the library and user programs will be polluted with the prefix
> `Overloaded'. I doubt of whether it worth to do this even if it is
> abbreviated to a single letter `O'. A mathematician knows the word
> Group, and one will be forced to find out what is OGroup.
> I consider re-declaring structures like this:
>
> record Setoid {c} ℓ (Carrier : Set c) : Set (suc (c ⊔ ℓ)) where
> infix 4 _≈_
> field
> _≈_ : Rel Carrier ℓ
> isEquivalence : IsEquivalence _≈_
>
> -- after the suggestion by Guillaume Brunerie.
> And if the user needs a Standard structure, one renames it to
> Setoid-std, Semigroup-std, and so on.
>
> Overloading for the above Setoid operations works like this:
>
> open Setoid {{...}}
>
> module _ {α α= β β=} (C : Set α) (C' : Set β)
> {{S : Setoid α= C}} {{S' : Setoid β= C'}}
> where
> IsCongruent : (C → C') → Set _
> IsCongruent f =
> {x y : C} → x ≈ y → (f x) ≈ (f y)
> -- --
>
> (1) Can this approach be extended to further generic structures?
>
> Also I do not understand the meaning of the `instance' language
> construct.
> I know its meaning in Haskell: an instance of a class.
> I expect, that theoretically, this corresponds to a pair: a theory and
> its model.
> Now, Standard library for Agda declares, for example, Setoid
> (which somewhat corresponds to some class) and also gives an
> implementation for the Setoid instance for Nat (natural numbers)
> -- without setting the word `instance'.
> Also it gives an implementation to build the Setoid `pointwise' instance
> for List A, from a Setoid instance over the type A -- without setting
> the word `instance'.
>
> (2) In the above intended `overloading' library where it will need to
> appear the `instance' key word?
>
> I thank people in advance for possible explanation.
>
> ------
> Sergei
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.chalmers.se/pipermail/agda/attachments/20181114/db8e881c/attachment.sig>
More information about the Agda
mailing list