Description
I found that the current way of defining a class that has a superclass does not play nice with instance search. Here is a small example using the Alternative
typeclass and its ApplicativeZero
superclass:
open import Data.List.Base using (List; []; _∷_; [_])
open import Function.Base
open import Level using (Level)
open import Category.Functor renaming (RawFunctor to Functor)
open import Category.Applicative
renaming ( RawApplicative to Applicative
; RawApplicativeZero to ApplicativeZero
; RawAlternative to Alternative
)
open Functor {{...}} using (_<$>_)
open Applicative {{...}} using ()
open ApplicativeZero {{...}} using () renaming (∅ to empty)
open Alternative {{...}} using () renaming (_∣_ to _<|>_)
variable
ℓ ℓ′ : Level
A B C : Set ℓ
F M : Set ℓ → Set ℓ′
choice1 : {{_ : Alternative F}} → List (F A) → F A
choice1 [] = empty
where instance applicativeZeroF = Alternative.applicativeZero it
choice1 (f ∷ []) = f
choice1 (f ∷ fs) = f <|> choice1 fs
This example is accepted, but it is awkward to have to declare the instance applicativeZeroF
locally.
In the Agda user manual, it is recommended to use instance fields for encoding superclasses: https://agda.readthedocs.io/en/v2.6.2/language/record-types.html#instance-fields. Unfortunately Agda currently does not provide a way to change a normal field to an instance field when importing a module. So the only solution I can see is to change the definition of these record types in the standard library to use instance fields from the beginning. Making these fields into instance fields should not change anything for people not using instance search, except that the type of the record constructor changes. But actually RawIAlternative
currently does not have a record constructor, so AFAICT the change should be 100% backwards compatible.
Also pinging @UlfNorell since he might know alternative solutions.