Instance search requires that all found solutions are unique. According to the Agda wiki (https://agda.readthedocs.io/en/v2.6.0.1/language/instance-arguments.html, bottom of the page),
From the previous stage we get a list of potential solutions. If the list is empty we fail with an error saying that no instance for C vs could be found (no). If there is a single solution we use it to solve the goal (yes), and if there are multiple solutions we check if they are all equal. If they are, we solve the goal with one of them (yes), but if they are not, we postpone instance resolution (maybe), hoping that some of the maybes will turn into nos once we know more about the involved metavariables.
Here I have some code that uses rose trees of bools. There are two data structures Trues
and Falses
that witness that the contents of a rose tree is all true or all false, respectively. There is also a function Opp
that swaps all trues to falses and vice-versa. Naturally, Trues x -> Falses (Opp x)
and vice-versa, so I wrote a function OppTF
to witness this. However, Agda now complains that there are two ways to prove Falses (B [])
, either directly with the constructor for Falses
, or via the function OppTF
. Of course, both of these produce the same result, and I prove this with the uniq
function that proves that if p : Trues (B [])
then p
is unique. Nevertheless, Agda does not realise this.
How can I convince Agda that all solutions are equal? Unfortunately I cannot make the proof irrelevant with .{{ _ : Falses x }}
as I need it later on. So I need to do one of the following:
uniq
proof to convince Agda that all solutions are equal.Is it possible to do any of these, and if so, how?
Code and error below:
module Example where
open import Data.List
open import Data.Bool
open import Relation.Binary.PropositionalEquality
data Rose : Set where
V : Bool → Rose
B : List Rose → Rose
Opp : Rose → Rose
Opp' : List Rose → List Rose
Opp (V x) = V (not x)
Opp (B xs) = B (Opp' xs)
Opp' [] = []
Opp' (x ∷ xs) = Opp x ∷ Opp' xs
data Trues : Rose → Set
data Trues' : List Rose → Set
data Trues where
instance VTrues : Trues (V true)
instance TTrues : ∀ {ts} ⦃ _ : Trues' ts ⦄ → Trues (B ts)
data Trues' where
instance VTrues' : Trues' []
instance TTrues' : ∀ {t ts} ⦃ _ : Trues t ⦄ ⦃ _ : Trues' ts ⦄ → Trues' (t ∷ ts)
data Falses : Rose → Set
data Falses' : List Rose → Set
data Falses where
instance VFalses : Falses (V false)
instance TFalses : ∀ {ts} ⦃ _ : Falses' ts ⦄ → Falses (B ts)
data Falses' where
instance VFalses' : Falses' []
instance TFalses' : ∀ {t ts} ⦃ _ : Falses t ⦄ ⦃ _ : Falses' ts ⦄ → Falses' (t ∷ ts)
instance
OppTF : ∀ {x} ⦃ _ : Trues x ⦄ → Falses (Opp x)
OppTF' : ∀ {xs} ⦃ _ : Trues' xs ⦄ → Falses' (Opp' xs)
OppTF {x} ⦃ VTrues ⦄ = VFalses
OppTF {x} ⦃ TTrues ⦃ xs ⦄ ⦄ = TFalses ⦃ OppTF' ⦃ xs ⦄ ⦄
OppTF' {[]} ⦃ VTrues' ⦄ = VFalses'
OppTF' {x ∷ xs} ⦃ TTrues' ⦃ p ⦄ ⦃ ps ⦄ ⦄ = TFalses' ⦃ OppTF ⦃ p ⦄ ⦄ ⦃ OppTF' ⦃ ps ⦄ ⦄
data Str : Rose → Set where
Tor : ∀ {x : Rose} → Str x
dummy : ∀ {x : Rose} ⦃ _ : Falses x ⦄ → Rose
dummy {x} = x
test : Rose
test = dummy {B []}
uniq : ∀ {p : Falses (B [])} → p ≡ TFalses ⦃ VFalses' ⦄
uniq {TFalses {_} ⦃ VFalses' ⦄} = refl
Error:
Failed to solve the following constraints:
Resolve instance argument _70 : Falses (B [])
Candidates
TFalses : {ts : List Rose} ⦃ _ : Falses' ts ⦄ → Falses (B ts)
OppTF : {x : Rose} ⦃ _ : Trues x ⦄ → Falses (Opp x)
(stuck)
This was solved over on the Zulip chat with the option
{-# OPTIONS --overlapping-instances #-}
In this particular case, allowing overlapping instances doesn't cause a slowdown, however in my actual use-case it did, so also adding
{-# OPTIONS --overlapping-instances --instance-search-depth 10 #-}
greatly sped it up (the default search depth is 500).