I'd like to match on an 'existentially hidden' type index, in order to write an Eq instance:
module Test
import Data.Vect
data Meep : Type where
Moop : {n:Nat} -> Vect n Int -> Meep
Eq Meep where
(Moop {n1} v1) == (Moop {n2} v2) = False
Subsequently, I'd like to have a view into decEq n1 n2 to delegate to Eq (Vect n Int) or to return False.
But the above doesn't seem to work:
Type checking .\.\Test.idr
.\.\Test.idr:9:9:
When checking left hand side of Prelude.Interfaces.Test.Meep implementation of Prelude.Interfaces.Eq, method ==:
n1 is not an implicit argument of Test.Moop
What is the actual Idris way of doing this?
You can do it this way:
Eq Meep where
(Moop {n = n1} v1) == (Moop {n = n2} v2) with (decEq n1 n2)
(Moop {n = n2} v1) == (Moop {n = n2} v2) | (Yes Refl) = v1 == v2
(Moop {n = n1} v1) == (Moop {n = n2} v2) | (No contra) = False
Related
I was trying to prove that replicate1 works correctly by showing that all elements of replicate1 n x are x:
all1 : (p : a -> Bool) -> List a -> Bool
all1 p [] = True
all1 p (x :: xs) = p x && all1 p xs
replicate1 : (n: Nat) -> a -> List a
replicate1 Z x = [x]
replicate1 (S k) x = x :: replicate1 k x
all_replicate_is_x : Eq a => {x: a} -> all1 (== x) (replicate1 n x) = True
all_replicate_is_x {n = Z} = ?hole
all_replicate_is_x {n = (S k)} = ?all_replicate_is_x_rhs_2
The base case hole is
Test.hole [P]
`-- a : Type
constraint : Eq a
x : a
-----------------------------------------
Test.hole : x == x && Delay True = True
How to prove this?
I have a function count in idris, defined as :
count : Eq a => a -> Vect n a -> Nat
count x [] = Z
count x (y::ys) = with (x == y)
| True = S (count x ys)
| False = count x ys
And a proof of the maximum value count can return:
countLTELen : Eq a => (x : a) -> (l : Vect n a) -> LTE (count x l) n
countLTELen x [] = lteRefl
countLteLen x (y::ys) with (x == y)
| True = LTESucc (countLTELen x ys)
| False = lteSuccRight (countLTELen x ys)
which is all well and good. I now want to write a function which removes all of an element from a list, removeAll :
removeAll : Eq a => (x : a) -> (l : Vect n a) -> Vect (n - (count x l)) a
removeAll x [] = []
removeAll x (y::ys) with (x == y)
| True = removeAll x ys
| False = x :: removeAll x ys
But this definition gives an error:
|
56 | removeAll : Eq a => (x : a) -> (l : Vect n a) -> Vect (n - (count x l)) a
| ^
When checking type of Proof.removeAll:
When checking argument smaller to function Prelude.Nat.-:
Can't find a value of type
LTE (count a n constraint x l) n
How can I use my proof to inform Idris that this type signature is correct?
Right now, Idris can't find the proof {auto smaller : LTE n m} for (-).
So either you need to be explicit:
removeAll : Eq a => (x : a) -> (l : Vect n a) ->
Vect ((-) {smaller=countLTELen x l} n (count x l) ) a
Or, because smaller is an auto-argument, you can hint the compiler to your proof function. Then this function will be tried when auto-finding a value for LTE (count x l) n.
%hint
countLTELen : Eq a => (x : a) -> (l : Vect n a) -> LTE (count x l) n
Given this definition:
data LType : Type where
TNat : LType
TFun : LType -> LType -> LType
Eq LType where
(==) TNat TNat = True
(==) (TFun l0 l1) (TFun r0 r1) = (l0 == r0) && (l1 == r1)
(==) _ _ = False
I am trying to prove the following:
ltype_eq : (t : LType) -> (t == t) = True
However I am getting stuck in an infinite number of proofs:
ltype_eq : (t : LType) -> (t == t) = True
ltype_eq TNat = Refl
ltype_eq (TFun x y) = ?ltype_eq_rhs_2
with the type of ?ltype_eq_rhs_2 being:
x : LType
y : LType
--------------------------------------
ltype_eq_rhs_2 : Main.LType implementation of Prelude.Interfaces.Eq, method == x
x &&
Delay (Main.LType implementation of Prelude.Interfaces.Eq, method == y
y) =
True
So it is basically a recursive proof. Any ideas on how to prove it?
I realised how to prove it right after posting. Here is the proof:
ltype_eq : (t : LType) -> (t == t) = True
ltype_eq TNat = Refl
ltype_eq (TFun x y) =
rewrite ltype_eq x in
rewrite ltype_eq y in
Refl
I'm building a little dependently-typed lambda calculus interpreter:
import Data.Vect
%default total
{- fin helper functions and lemmas -}
incrFin : Fin n -> Fin (S n) -> Fin (S n)
incrFin x FZ = FS x
incrFin FZ (FS y) = FZ
incrFin (FS x) (FS y) = FS (incrFin x y)
subrFin : (x : Fin (S n)) -> (y : Fin (S n)) -> (x = y -> Void) -> Fin n
subrFin FZ FZ neq = absurd (neq Refl)
subrFin FZ (FS x) neq = x
subrFin {n = S n} (FS x) FZ neq = FZ
subrFin {n = S n} (FS x) (FS y) neq = FS (subrFin x y (\Refl => neq Refl))
indexOfIncrFin : (x : Fin (S n)) -> (y : Fin n) -> (env : Vect n a) -> (t : a) ->
index (incrFin y x) (insertAt x t env) = index y env
{- elided -}
indexOfSubrFin : {n : Nat} -> {env : Vect n a} -> (neq : (x = y) -> Void) ->
index (subrFin x y neq) env = index y (insertAt x t2 env)
{- elided -}
indexInsertAt : (x : Fin (S n)) -> (t : a) -> (env : Vect n a) -> index x (insertAt x t env) = t
{- elided -}
incrFinChanges : (x : Fin n) -> (y : Fin (S n)) -> Not (incrFin x y = y)
{- elided -}
{- main code -}
data Ty = Base | Arrow Ty Ty
data Expr : Vect n Ty -> Ty -> Type where
Var : (x : Fin n) -> index x env = t -> Expr env t
Con : Expr env Base
App : Expr env (Arrow t1 t2) -> Expr env t1 -> Expr env t2
Abs : (t1 : Ty) -> Expr (t1 :: env) t2 -> Expr env (Arrow t1 t2)
incr : (x : Fin (S n)) -> (tt : Ty) -> Expr env t -> Expr (insertAt x tt env) t
incr x tt (Var y Refl) {env = env} = Var (incrFin y x) (indexOfIncrFin x y env tt)
incr x tt Con = Con
incr x tt (App e1 e2) = App (incr x tt e1) (incr x tt e2)
incr x tt (Abs t1 e) = Abs t1 (incr (FS x) tt e)
subst : (x : Fin (S n)) -> Expr env t' -> Expr (insertAt x t' env) t -> Expr env t
subst {env = env} {t' = t'} x e' (Var y pf) with (decEq x y)
subst {env = env} {t' = t'} x e' (Var x Refl) | Yes Refl = rewrite indexInsertAt x t' env in e'
subst {env = env} {t' = t'} x e' (Var y Refl) | No neq = Var (subrFin x y neq) (indexOfSubrFin neq)
subst x e' Con = Con
subst x e' (App e1 e2) = App (subst x e' e1) (subst x e' e2)
subst x e' (Abs t1 e) = Abs t1 (subst (FS x) (incr FZ t1 e') e)
substIncr : (x : Fin (S n)) -> (e' : Expr env t') -> (e : Expr env t) -> subst x e' (incr x t' e) = e
substIncr x e' (Var y Refl) with (decEq x (incrFin y x))
substIncr x e' (Var y Refl) | Yes eq = absurd (incrFinChanges y x (sym eq))
substIncr x e' (Var y Refl) | No neq = ?substIncr_missingCase
substIncr x e' Con = Refl
substIncr x e' (App e1 e2) = rewrite substIncr x e' e1 in rewrite substIncr x e' e2 in Refl
substIncr x e' (Abs t1 e) = rewrite substIncr (FS x) (incr FZ t1 e') e in Refl
The problem is the last missing case of the substIncr proof. The type won't reduce, because subst only reduces when the proof in Var is identically Refl, and instead it's indexOfIncrFin x y env t'. Now, indexOfIncrFin is total, it always returns Refl, but its type isn't just f x y = z; it, instead, has a complicated term on either side of the equality (index (incrFin y x) (insertAt x t env) = index y env). So when I try to match on it, via with or case, it complains about "type mismatch between index y env = index y env (type of Refl) and index (incrFin y x) (insertAt x t' env) = index y env (expected type)."
The only other thing I could think of was to change the definition of subst to rewrite instead of matching on Refl, but that (a) is kinda uglier, and (b) bogs me down in some kind of rewrite__impl type I understand even less, and which also won't reduce.
Any ideas on how to work around this?
Given:
*section3> :module Data.Vect
*section3> :let e = the (Vect 0 Int) []
*section3> :let xs = the (Vect _ _) [1,2]
*section3> decEq xs e
(input):1:7:When checking argument x2 to function Decidable.Equality.decEq:
Type mismatch between
Vect 0 Int (Type of e)
and
Vect 2 Integer (Expected type)
Specifically:
Type mismatch between
0
and
2
Why must the Nat arguments equal each other for DecEq?
Note - posted in https://groups.google.com/forum/#!topic/idris-lang/qgtImCLka3I originally
decEq is for homogenous propositional equality:
||| Decision procedures for propositional equality
interface DecEq t where
||| Decide whether two elements of `t` are propositionally equal
total decEq : (x1 : t) -> (x2 : t) -> Dec (x1 = x2)
As you can see, x1 and x2 are both of type t. In your case, you have x1 : Vect 2 Integer and x2 : Vect 0 Int. These are two different types.
You can write your own heterogenous equality decider for Vectors of the same element type by first checking their lengths, then delegating to the homogenous version:
import Data.Vect
vectLength : {xs : Vect n a} -> {ys : Vect m a} -> xs = ys -> n = m
vectLength {n = n} {m = n} Refl = Refl
decEqVect : (DecEq a) => (xs : Vect n a) -> (ys : Vect m a) -> Dec (xs = ys)
decEqVect {n = n} {m = m} xs ys with (decEq n m)
decEqVect xs ys | Yes Refl = decEq xs ys
decEqVect xs ys | No notEq = No (notEq . vectLength)