Prove So (0 < m) -> (n ** m = S n) - proof

I'm trying to make an Idris function of type (j : Nat) -> {auto p : So (j < n)} -> Fin n to convert a Nat into a Fin n. To get the Z case to work (and output FZ), I'm trying to prove that a proof of 0 < n is sufficient to be able to make FZ : Fin n. But I can't work out how to do this.
I'm open to making a completely different function, as long as it can convert Nat values into Fin n values (where they exist). My goal is to have some other function that can convert any Nat into a Mod n value, so that, for example, 15 : Nat is mapped to 3 : Mod 4. My Mod type currently has a single constructor, mkMod : Fin n -> Mod n.

After learning about LT : Nat -> Nat -> Type, I took a different approach. I started with the declaration:
natToFin : (j : Nat) -> {auto p : j `LT` n} -> Fin n
natToFin {n} j {p} = ?natToFin_rhs_1
. Case-splitting on n, then on p in the n = Z case resulted in:
natToFin : (j : Nat) -> {auto p : j `LT` n} -> Fin n
natToFin {n = (S k)} j {p = p} = ?natToFin_rhs_2
, which is essentially the proof I was asking for. From there, I case-split on j and filled the zero case, leaving:
natToFin : (j : Nat) -> {auto p : j `LT` n} -> Fin n
natToFin {n = (S k)} Z = FZ
natToFin {n = (S k)} (S j) {p = p} = ?natToFin_rhs_3
. I wanted to fill ?natToFin_rhs_3 with FS (natToFin j), but the type checker wasn't letting me. However, after a case split on p, it was fine:
natToFin : (j : Nat) -> {auto p : j `LT` n} -> Fin n
natToFin {n = (S k)} Z = FZ
natToFin {n = (S k)} (S j) {p = (LTESucc x)} = FS (natToFin j)
Finally, I added total, and it all checked out.
The only problem now is that Idris can't seem to find LT proofs automatically. This is what happens:
λΠ> the (Fin 6) (natToFin 2)
When elaborating argument p to function mod2.natToFin:
Can't solve goal
LT (fromInteger 2) (fromInteger 6)
Is there any way to fix that?

Related

Proving if n = m and m = o, then n + m = m + o in Idris?

I am trying to improve my Idris skill by looking at some of the exercises Software Foundations (originally for Coq, but I am hoping the translation to Idris not too bad). I am having trouble with the "Exercise: 1 star (plus_id_exercise)" which reads:
Remove "Admitted." and fill in the proof.
Theorem plus_id_exercise : ∀ n m o : nat,
n = m → m = o → n + m = m + o.
Proof.
(* FILL IN HERE *) Admitted.
I have translated to the following problem in Idris:
plusIdExercise : (n : Nat) ->
(m : Nat) ->
(o : Nat) ->
(n == m) = True ->
(m == o) = True ->
(n + m == m + o) = True
I am trying to perform a case by case analysis and I am having a lot of issues. The first case:
plusIdExercise Z Z Z n_eq_m n_eq_o = Refl
seems to work, but then I want to say for instance:
plusIdExercise (S n) Z Z n_eq_m n_eq_o = absurd
But this doesn't work and gives:
When checking right hand side of plusIdExercise with expected type
S n + 0 == 0 + 0 = True
Type mismatch between
t -> a (Type of absurd)
and
False = True (Expected type)
Specifically:
Type mismatch between
\uv => t -> uv
and
(=) FalseUnification failure
I am trying to say this case can never happen because n == m, but Z (= m) is never the successor of any number (n). Is there anything I can do to fix this? Am I approaching this correctly? I am somewhat confused.
I would argue that the translation is not entirely correct. The lemma stated in Coq does not use boolean equality on natural numbers, it uses the so-called propositional equality. In Coq you can ask the system to give you more information about things:
Coq < About "=".
eq : forall A : Type, A -> A -> Prop
The above means = (it is syntactic sugar for eq type) takes two arguments of some type A and produces a proposition, not a boolean value.
That means that a direct translation would be the following snippet
plusIdExercise : (n = m) -> (m = o) -> (n + m = m + o)
plusIdExercise Refl Refl = Refl
And when you pattern-match on values of the equality type, Idris essentially rewrites terms according to the corresponding equation (it's roughly equivalent to Coq's rewrite tactic).
By the way, you might find the Software Foundations in Idris project useful.

Function to return a part of a list

I am new to Haskell and have an assignment. I have to write a
Int->Int->[u]->[u]
Function that is given input two Ints i and j and a list and returns the elements that are in possitions greater than i and smaller than j. What I have thought so far is:
fromTo :: Int->Int->[u]->[u]
fromTo i j (h:t)
|i == 1 && j == length(h:t)
= (h:t)
|i /= 1
fromTo (i-1) j t
|j /= length(h:t)
fromTo i j init(h:t)
However I get a syntax error for the second |. Also im unsure if my train of thought is correct here.
(init returns the list without its last element)
EDIT: Corrected
|i /= 1
fromTo (i-1) j (h:t)
to
|i /= 1
fromTo (i-1) j t
Fixed indentation, parenthesization, and missing =s. This reformation compiles, and works for ordinals and finite non-empty lists:
fromTo :: Int -> Int -> [u] -> [u]
fromTo i j (h : t)
| i == 1 && j == length (h : t) = h : t
| i /= 1 = fromTo (i - 1) j t
| j /= length (h : t) = fromTo i j (init (h : t))
I think you're looking for something like this pointfree, naturally indexing span:
take :: Int -> [a] -> [a]
take _ [] = []
take 0 _ = []
take n (x : xs) = x : take (n - 1) xs
drop :: Int -> [a] -> [a]
drop _ [] = []
drop 0 xs = xs
drop n (_ : xs) = drop (n - 1) xs
span :: Int -> Int -> [a] -> [a]
span i j = drop i . take (j + 1)
which
span 0 3 [0 .. 10] == [0,1,2,3]
Or, to fit the specification:
between :: Int -> Int -> [a] -> [a]
between i j = drop (i + 1) . take j
which
between 0 3 [0 .. 10] == [1,2]
You're missing = between the | guard clause and the body. The Haskell compiler thinks the whole thing is the guard, and gets confused when it runs into the next | guard because it expects a body first. This will compile (although it is still buggy):
fromTo :: Int -> Int -> [u] -> [u]
fromTo i j (h:t)
| i == 1 && j == length (h:t) =
(h:t)
| i /= 1 =
fromTo (i-1) j t
| j /= length (h:t) =
fromTo i j (init (h:t))
but I would say there are better ways of writing this function. For example, in principle a function like this should work on infinite lists, but your use of length makes that impossible.
Here is complete solution that use recursion:
fromTo :: Int -> Int -> [u] -> [u]
fromTo i j xs = go i j xs []
where go i j (x:xs) rs
| i < 0 || j < 0 = []
| i > length (x:xs) || j > length (x:xs) = []
| i /= 0 = go (i - 1) j t
| j /= 1 = goo i (j -1) (rs ++ [x])
| otherwise = rs
Notes:
go is standard Haskell idiom for recursive function that need extra parameters compared to main level function.
First clause make sure that negative indexes result in empty list. Second does the same for any index that exceed size of a list. Lists must be finite. Third "forgets" head of the array i times. Fourth will accumulate "next" (j - 1) heads into rs. Fifth clause will be triggered when all indexes are "spent" and rs contain result.
You could make it work on infinite lists. Drop second clause. Return rs if xs is empty before "exhausting" indexes. Then function will take "up to" (j-1) elements from i.

Proving identity for binary operator on Fin

I've defined an operator, +- (ignore the terrible name), as follows:
infixr 10 +-
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n} {m} FZ f' = rewrite plusCommutative n m in weakenN n f'
(+-) {n = S n} (FS f) f' = FS (f +- f')
The intention is that it behaves exactly like + as defined on Fin, but the upper bound of the result is tighter by 1. As far as I can tell, it works correctly.
The problem I'm having is in trying to prove that (FZ +- f) = f for any f : Fin n. I'm not expecting this to be true in general, because it will usually be the case that FZ +- f has a looser bound than f on account of the call to weakenN. However, in the particular case where the FZ has type Fin 1, then the types (and the values) ought to match up.
Is there any way of indicating to Idris that I only want to assert the equality in that particular case, rather than for all possible types of FZ? Or is there a completely different approach that I ought to be taking?
If we reshuffle the definition for (+-) a bit, the proof becomes easy:
import Data.Fin
infixr 10 +-
total
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n = Z} {m = m} a b = b
(+-) {n = (S n)}{m = m} FZ b = rewrite plusCommutative (S n) m in weakenN (S n) b
(+-) {n = (S n)}{m = m} (FS a) b = FS (a +- b)
lem : (f : Fin (S n)) -> the (Fin 1) FZ +- f = f
lem FZ = Refl
lem (FS x) = Refl
This checks out because the rewrite on the right hand side of the (+-) definition happens to normalize to concrete values instead of substitutions/coercions.
On the other hand, if we'd like to stick with the original definition for (+-), then the rewrite doesn't go away, and we're in for a whole world of pain, because now we have to work with heterogeneous equalities. I did a proof with heterogeneous equalities in Agda, however I couldn't get it to work in Idris on short notice, and I believe making it work would be a rather painful experience. Here it is in Agda.
Note though that we would have to add one more case to the original definition in order to make proving properties about it feasible in the first place. That's because it doesn't pass the coverage checker as it is. It's evident to us that Fin 1 only has FZ as constructor, but this has to be also explained to the compiler:
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n} {m} FZ f' = rewrite plusCommutative n m in weakenN n f'
(+-) {n = Z} (FS FZ) f' impossible
(+-) {n = S n} (FS f) f' = FS (f +- f')

unresolved metas when defining a record in Agda

Consider the following code:
module UnresolvedMeta where
record Test (M : Set) : Set1 where
field
_≈_ : M -> M -> Set
_⊕_ : M -> M -> M
assoc⊕ : ∀ {r s t} -> ((r ⊕ s) ⊕ t) ≈ (r ⊕ (s ⊕ t))
data ℕ : Set where
n0 : ℕ
suc : ℕ -> ℕ
data _==_ : ℕ -> ℕ -> Set where
refl== : ∀ {k} -> k == k
_+_ : ℕ -> ℕ -> ℕ
k + n0 = k
k + suc m = suc (k + m)
lem-suc== : ∀ {k m} -> k == m -> suc k == suc m
lem-suc== refl== = refl==
assoc+ : ∀ {i j k} -> ((i + j) + k) == (i + (j + k))
assoc+ {i} {j} {n0} = refl== {i + j}
assoc+ {i} {j} {suc k} = lem-suc== (assoc+ {i} {j} {k})
thm-ℕ-is-a-test : Test ℕ
thm-ℕ-is-a-test = record {
_⊕_ = _+_;
_≈_ = _==_;
assoc⊕ = assoc+
}
When loaded with Agda (version 2.3.2.2), Agda prints an error "Unsolved metas at the following locations" pertaining to the line penultimate line:
assoc⊕ = assoc+
and specifically pointing to assoc+.
How do I provide a hint or otherwise change the code so it compiles without this warning?
I can of course get rid of it by unhiding the arguments, but that means I would have to specify explicit arguments everywhere, even in places where it is not needed...
You can exploit the fact that Agda allows you to specify implicit arguments even inside a lambda abstraction. More specifically, you can write this:
λ {r s t} → assoc+ {r} {s} {t}
-- with a type {r s t : ℕ} → ((r + s) + t) == (r + (s + t))
And indeed, replacing assoc+ with the expression above makes the compiler happy. It would seem that the unification has a problem with the last argument (t), so we can even ignore r and s and only fill in t explicitly:
assoc⊕ = λ {_ _ t} → assoc+ {k = t}

Using coq, trying to prove a simple lemma on trees

Trying to prove correctness of a insertion function of elements into a bst I got stuck trying to prove a seemingly trivial lemma.
My attempt so far:
Inductive tree : Set :=
| leaf : tree
| node : tree -> nat -> tree -> tree.
Fixpoint In (n : nat) (T : tree) {struct T} : Prop :=
match T with
| leaf => False
| node l v r => In n l \/ v = n \/ In n r
end.
(* all_lte is the proposition that all nodes in tree t
have value at most n *)
Definition all_lte (n : nat) (t : tree) : Prop :=
forall x, In x t -> (x <= n).
Lemma all_lte_trans: forall n m t, n <= m /\ all_lte n t -> all_lte m t.
Proof.
intros.
destruct H.
unfold all_lte in H0.
unfold all_lte.
intros.
Clearly if everything in the tree is smaller than n and n <= m everything is smaller than m, but I cannot seem to make coq believe me. How do I continue?
You have to use the le_trans theorem :
le_trans: forall n m p : nat, n <= m -> m <= p -> n <= p
that comes from Le package.
It meas that you have to import Le or more generally Arith with :
Require Import Arith.
at the beginning of your file. Then, you can do :
eapply le_trans.
eapply H0; trivial.
trivial.