Why is chain of equational reasoning failing to meet trivially solvable constraints? - agda

The following Agda code:
module test where
open import Data.Float
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_)
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; step-≡; _∎)
postulate
distrib : {m a b : Float} → m * (a + b) ≡ (m * a) + (m * b)
dbg : (m a b : Float) → m * (a + b) ≡ (m * a) + (m * b)
dbg m a b =
begin
m * (a + b)
≡⟨ distrib ⟩ -- (Line "22")
(m * a) + (m * b)
∎
yields:
_m_18 : Float [ at /Users/dbanas/Documents/Agda/agda_misc/test.agda:22,6-13 ]
_a_19 : Float [ at /Users/dbanas/Documents/Agda/agda_misc/test.agda:22,6-13 ]
_b_20 : Float [ at /Users/dbanas/Documents/Agda/agda_misc/test.agda:22,6-13 ]
———— Errors ————————————————————————————————————————————————
Failed to solve the following constraints:
(_m_18 * _a_19) + (_m_18 * _b_20) = (m * a) + (m * b) : Float
_m_18 * (_a_19 + _b_20) = m * (a + b) : Float
after I type C-c C-l.
(Note: "22,6-13" identifies the second occurrence of the word "distrib".)
I don't understand why the constraints can't be met.
They seem trivially solvable:
_m_18 = m
_a_19 = a
_b_20 = b

While those solutions are correct, they're not inevitable, because multiplication and addition are not injective. In this case, you can fill in just m in line 22, ie distrib {m = m}.

Related

Agda - Why is this case required to type check? In a simple proof that $forall m, 1 * m \equiv m$

After defining the naturals, addition and multiplication as usual, I set to write a proof that 1 is a neutral element.
p : (n : ℕ) -> (1 * n) ≡ n
p zero = refl
p (suc m) = refl
Which is fine!
Since refl appears in both alternatives, I thought this should type-check:
p : (n : ℕ) -> (1 * n) ≡ n
p _ = refl
But this fails with:
1 * n != n of type ℕ
when checking that the expression refl has type (1 * n) ≡ n
What causes type to not check here?
It's hard to diagnose an error without a MRE, no matter how standard you think your definitions are.
Your error presumably comes from the fact _+_ and _*_ are defined like so:
0 + n = n
m + 0 = m
suc m + n = suc (m + n)
0 * n = n
suc m * n = n + m * n
and so 1 * n = (suc 0) * n = n + 0 * n = n + 0 which is not judgmentally
equal to n because _+_ is strict in its first argument and so won't
evaluate until that first argument is constructor-headed.
Matching on n to expose a constructor is enough for _+_ to reduce:
0 + 0 is 0 by the first equation and suc m + 0 is suc m by the second.

Could not parse the left-hand side (m + 1) * n

I just started learning Agda reading Programming Language Foundations in Agda. Right in the first chapter there's a definition of multiplication with one of the cases being (suc m) * n = n + (m * n). I assumed it could be nicer expressed as (m + 1) * n = n + (m * n), but apparently this is not the case. The following program:
data ℕ : Set where
zero : ℕ
suc : ℕ → ℕ
_+_ : ℕ → ℕ → ℕ
zero + n = n
(suc m) + n = suc (m + n)
{-# BUILTIN NATURAL ℕ #-}
_*_ : ℕ → ℕ → ℕ
zero * n = zero
-- This is fine:
-- (suc m) * n = n + (m * n)
-- This is not:
(m + 1) * n = n + (m * n)
fails with:
Could not parse the left-hand side (m + 1) * n
Operators used in the grammar:
* (infix operator, level 20) [_*_ (/Users/proxi/Documents/Projekty/Agda/multiply.agda:11,1-4)]
+ (infix operator, level 20) [_+_ (/Users/proxi/Documents/Projekty/Agda/multiply.agda:5,1-4)]
when scope checking the left-hand side (m + 1) * n in the
definition of _*_
I believe in Agda terms one could say that definition using constructor works fine, but definition using operator does not. Why is that so? Is this never possible, or does it depend on how operator (function) is defined?
Using functions in patterns is not supported.
Note also that if functions were allowed in patterns, it would be (1 + m) * n rather than (m + 1) * n, because _+_ is defined by pattern matching on its first argument, so 1 + m reduces to suc m and m + 1 is stuck.
As has been pointed out, you cannot just use a function to pattern-match. However, it is possible to declare pattern-matching extensions that express nearly the same thing:
open import Data.Nat.Base as Nat
using (ℕ; zero) renaming (suc to 1+_)
pattern 2+_ n = 1+ 1+ n
Then you can use (1+ m) * n, and even (2+ m).

How do I handle the higher inductive cases when defining functions on HITs?

I'm experimenting with Homotopy Type Theory in Agda. I use HITs to define the integers:
{-# OPTIONS --cubical --safe #-}
open import Cubical.Foundations.Prelude
open import Data.Nat using (ℕ; _+_)
data ℤ : Set where
-- | An integer i is a pair of natural numbers (m, n)
-- where i = m - n
int : ℕ → ℕ → ℤ
-- | (a, b) = (c, d)
-- a - b = c - d
-- a + d = b + c
int-eq : ∀ {a b c d : ℕ} → (a + d ≡ b + c) → int a b ≡ int c d
Now, I want to define addition on the integers:
add-ints : ℤ → ℤ → ℤ
add-ints (int a b) (int c d) = int (a + c) (b + d)
However, the compiler gives an error because I need to pattern match the equality constructors as well:
Incomplete pattern matching for add-ints. Missing cases:
add-ints (int-eq x i) (int x₁ x₂)
add-ints x (int-eq x₁ i)
when checking the definition of add-ints
So, I end up with this:
add-ints : ℤ → ℤ → ℤ
add-ints (int a b) (int c d) = int (a + c) (b + d)
add-ints (int-eq x i) (int c d) = { }0
add-ints (int a b) (int-eq x i) = { }1
add-ints (int-eq x i) (int-eq y j) = { }2
Agda's typed holes don't help:
?0 : ℤ
?1 : ℤ
?2 : ℤ
———— Errors ————————————————————————————————————————————————
Failed to solve the following constraints:
?0 (x = x) (i = i) (c = a) (d = b)
= ?2 (x = x) (i = i) (y = x₁) (j = i0)
: ℤ
?0 (x = x) (i = i) (c = c) (d = d)
= ?2 (x = x) (i = i) (y = x₁) (j = i1)
: ℤ
?1 (a = a₁) (b = b₁) (x = x₁) (i = i)
= ?2 (x = x) (i = i0) (y = x₁) (j = i)
: ℤ
?1 (a = c₁) (b = d₁) (x = x₁) (i = i)
= ?2 (x = x) (i = i1) (y = x₁) (j = i)
: ℤ
int (a + x) (b + x₁) = ?0 (x = x₂) (i = i0) (c = x) (d = x₁) : ℤ
int (c + x) (d + x₁) = ?0 (x = x₂) (i = i1) (c = x) (d = x₁) : ℤ
int (x + a) (x₁ + b) = ?1 (a = x) (b = x₁) (x = x₂) (i = i0) : ℤ
int (x + c) (x₁ + d) = ?1 (a = x) (b = x₁) (x = x₂) (i = i1) : ℤ
The Agda documentation gives examples of HIT usage, where it pattern matches on the equality constructors when operating on the torus and propositional truncation. However, as someone without a background in topology, I don't completely follow what's going on.
What is the purpose of the i and j from the [0, 1] interval, and why do they appear in my equality constructor patterns? How do I use i and j? How do I handle the higher inductive cases?
You can think of path constructors as taking an interval variable, and satisfying additional equations about the endpoints of that interval,
data ℤ : Set where
int : ℕ → ℕ → ℤ
int-eq : ∀ {a b c d : ℕ} → (a + d ≡ b + c) → I → ℤ
-- such that int-eq {a} {b} {c} {d} _ i0 = int a b
-- and int-eq {a} {b} {c} {d} _ i1 = int c d
In your equations for add-ints of int-eq you also have to produce a ℤ, and it has to match the first clause (for the int constructor) at both endpoints. These are the constraints that Agda reports, saying that the different clauses have to agree.
You can start with ?0 first. For which only the last two contraints matter. It helps here to fill in the implicit variables,
add-ints (int-eq {a0} {b0} {a1} {b1} x i) (int c d) = { }0
To match the first clause, you need to come up with a value of type ℤ that is equal to int (a0 + c) (b0 + d) when i = i0 and equal to int (a1 + c) (b1 + d) when i = i1. You can use an int-eq constructor for this,
?0 = int-eq {a0 + c} {b0 + d} {a1 + c} {b1 + d} ?4 i
The equality ?4 has to be worked out.

why this code is not working in agda?

I am trying to prove commutative property over natural number on multiplication operation.
--proving comm over *
*comm : ∀ a b → (a * b) ≡ (b * a)
*comm zero b = sym (rightId* b)
*comm (suc a) b = {!!}
when i check goal I found that it is b + a * b ≡ b * suc a. So i proved this.
lemma*-swap : ∀ a b → a + a * b ≡ a * suc b
Now when i tried :
*comm : ∀ a b → (a * b) ≡ (b * a)
*comm zero b = sym (rightId* b)
*comm (suc a) b = lemma*-swap b a
This should work as it satisfied the goal but why this is not working?? Please suggest me where I am wrong.
b + a * b (the expression in the goal) and a + a * b (the expression in lemma*-swap) are distinct so applying lemma*-swap does not satisfy the goal.
You need to rewrite the induction hypothesis *comm a b to turn a * b into b * a in the goal so that the expression lemma*-swap b a can be used to discharge the goal.

rewrite and equational reasoning in agda

With rewrite I have a succinct syntax (e.g. no congruence property invoked) and I can prove :
-- * is associative
*-assoc : ∀ a b c → (a * b) * c ≡ a * (b * c)
*-assoc zero b c = refl
*-assoc (succ a) b c rewrite *+-dist b (a * b) c | *-assoc a b c = refl
however, my small brain can parse better this proof
--written in equational style
*-assoc' : ∀ a b c → (a * b) * c ≡ a * (b * c)
*-assoc' zero b c = refl
*-assoc' (succ a) b c = (succ a * b) * c ≡⟨ refl ⟩
(b + a * b) * c ≡⟨ *+-dist b (a * b) c ⟩
b * c + (a * b) * c ≡⟨ cong (λ x -> b * c + x) (*-assoc a b c) ⟩
b * c + a * (b * c) ≡⟨ refl ⟩
(succ a) * (b * c) ∎
but I have to specify which subterm to 'transform' by invoking congruence.
Is there a way to combine rewrite and equational writing to get rid of the congruence mention ?
Thanks in advance

Resources