Instance search limitations

♀尐吖头ヾ 提交于 2020-01-02 10:03:39

问题


The instance arguments machinery is described in an old paper and at the Agda wiki. Are there some notable facts that these sources do not mention? What are limitations of instance search?


回答1:


Removing ambiguity

If we typecheck this:

open import Category.Functor
open import Category.Monad
open RawFunctor
open RawMonad

and run C-c C-w _<$>_ (C-c C-w is "explain why a particular name in scope"), we get (after some cleaning)

_<$>_ is in scope as
  * a record field Category.Functor.RawFunctor._<$>_
  * a record field Category.Monad.RawMonad._._<$>_

I.e. _<$>_ is ambiguous, so it's cumbersome to use monads and functors, that are not monads, in the same module, because you have to manually disambiguate between two _<$>_.

This can be cured with instance arguments. Instead of opening Functor in the definition of Monad (via Applicatve):

record RawIMonad ... where

  open RawIApplicative rawIApplicative public

we can provide an instance and let instance search do the job (the definitions of Applicative and Functor can be found here):

record Monad {α} (M : Set α -> Set α) : Set (suc α) where
  infixl 1 _>>=_

  field
    return : ∀ {A} -> A -> M A
    _>>=_  : ∀ {A B} -> M A -> (A -> M B) -> M B

  instance
    Monad<:Applicative : Applicative M
    Monad<:Applicative = record { pure = return ; _<*>_ = λ mf mx -> mf >>= λ f -> mx >>= return ∘ f }
open Monad {{...}}

Now there is only one _<$>_ — in the definition of Functor, but instance search sees, that a monad is an applicative and an applicative is a functor, so _<$>_ is defined on monads, because it's defined on functors.

Instance fields

At the moment you can't declare fields of records as instances:

record R : Set where
  field
    instance n : ℕ

The workaround is

record R : Set where
  field
    n : ℕ

   instance
     R->ℕ : ℕ
     R->ℕ = n

Weakness

Instance search doesn't cooperate with metavariables resolution.

instance
  fz : Fin 1
  fz = zero

z : ∀ {n} {{_ : Fin n}} -> ℕ
z = 0

yellow : z ≡ 0
yellow = refl

ok : z {1} ≡ 0
ok = refl

In yellow instance search doesn't find the fz instance. I was told, that this is the intended behaviour, but it looks too restrictive to me and I don't see any benefits.

One workaround is to use instance arguments in place of implicit arguments:

instance
  one : ℕ
  one = 1

  fz : Fin 1
  fz = zero

  z : ∀ {{n}} {{_ : Fin n}} -> ℕ
  z = 0

  now-ok : z ≡ 0
  now-ok = refl

Instances are always imported

module M where
  instance
    z : ℕ
    z = 0

z' : {{n : ℕ}} -> ℕ
z' {{n}} = n

ok : z' ≡ 0
ok = refl

The M module is not opened, but the instance is in scope. If you want to hide instances, use records:

record R : Set where
  instance
    z : ℕ
    z = 0

z' : {{n : ℕ}} -> ℕ
z' {{n}} = n

error : z' ≡ 0
error = refl

open R _

ok : z' ≡ 0
ok = refl

A nasty bug

We can rewrite ok as

ok : let open R _ in z' ≡ 0
ok = refl

But if define ok' below

ok' : z' ≡ 0
ok' = refl

The instance from R is not in scope, but Agda picks it anyway. The same holds for the value level. I.e. if you import a module or open a record, instances from it will be availaible for all definitions below, regardless of where you opened it.

Personal experience

I was fighting with instance arguments for two weeks or so, trying to implement some basic category theory in Agda, but instance search is unpredictable because of its weakness — adding a parameter to a record ruins everything. It's also hard to figure why everything is yellow — is it because you are doing something silly or because Agda refuses to resolve a trivial metavariable? When you have a type signature on six lines and several nested records, it's a matter of luck, whether you'll find a way to overcome instance search limitations or not.



来源:https://stackoverflow.com/questions/31544734/instance-search-limitations

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!