data T = A String | B String
p : ((A s) = (A s')) -> (s = s')
If I have (A s) = (A s'), how do I obtain s = s'?
P.S. I'm new to Idris. Feel free to edit my question for code style or to add pertinent keywords.
Pattern match on Refl:
data T = A String | B String
p : ((A s) = (A s')) -> (s = s')
p Refl = Refl
Related
I'm writing a function to test propositional equality of Nat, and it typechecks in Idris 1.
sameNat : (n : Nat) -> (m : Nat) -> Maybe (n = m)
sameNat Z Z = Just Refl
sameNat (S n) (S m) = case sameNat n m of
Just e => Just (cong e)
Nothing => Nothing
sameNat _ _ = Nothing
But it doesn't typecheck in Idris 2 (0.4.0) and I got this error.
Error: While processing right hand side of sameNat. When
unifying n = m and Nat m e -> :: ?x ?xs n m e.
Mismatch between: n = m and Nat m e -> :: ?x ?xs n m e.
It typechecks when I write a specific version of cong and use it.
cong' : n = m -> S n = S m
cong' Refl = Refl
Why doesn't this typecheck and how can I make it typecheck?
The type signature of cong changed:
Idris 1:
cong : (a = b) -> f a = f b
Idris 2:
Prelude.cong : (0 f : (t -> u)) -> a = b -> f a = f b
This code doesn't compile:
data Foo = A String | B (List Foo)
Eq Foo where
(==) (A x) (A y) = x == y
(==) (B xs) (B ys) = xs == ys
(==) _ _ = False
It yields the following error:
Type checking ./eq.idr eq.idr:11:3-27: | 11 | (==) (A x) (A y) =
x == y | ~~~~~~~~~~~~~~~~~~~~~~~~~ Prelude.Interfaces.Main.Foo
implementation of Prelude.Interfaces.Eq, method == is possibly not
total due to recursive path Prelude.Interfaces.Main.Foo implementation
of Prelude.Interfaces.Eq, method == --> Prelude.Interfaces.Main.Foo
implementation of Prelude.Interfaces.Eq, method ==
So is the problem here that we're relying on Eq Foo in its implementation, hence the recursive path? That doesn't seem to explain it, because this compiles:
data Bar = C String | D Bar
Eq Bar where
(==) (C x) (C y) = x == y
(==) (D x) (D y) = x == y
(==) _ _ = False
So - I can have recursive calls to == on whatever I'm defining the implementation on, but I can't to lists of it? Am I missing a trick to make this work, or am I trying to do something that's fundamentally broken somewhere?
The function that decides equality needs to be implemented in terms of mutual recursion, just as Foo itself is defined by mutual recursion.
Eq Foo where
(==) = eq
where mutual -- massive indentation necessary
eq : Foo -> Foo -> Bool
eq (A l) (A r) = l == r
eq (B l) (B r) = eq1 l r
eq _ _ = False
eq1 : List Foo -> List Foo -> Bool
eq1 (l :: ls) (r :: rs) = eq l r && eq1 ls rs
eq1 [] [] = True
eq1 _ _ = False
You can't reuse List's own (==), but it is possible to factor out a pattern.
zipWithFoldrElem : (ls : List a) -> (rs : List a) -> ((l : a) -> (r : a) -> Elem (l, r) (zip ls rs) -> b) -> (b -> Lazy b -> b) -> b -> b -> b -> b
zipWithFoldrElem [] [] _ _ e _ _ = e
zipWithFoldrElem [] (_ :: _) _ _ _ el _ = el
zipWithFoldrElem (_ :: _) [] _ _ _ _ er = er
zipWithFoldrElem (l :: ls) (r :: rs) f g e el er = f l r Here `g` zipWithFoldLazyElem ls rs (\l, r, e => f l r (There e)) g e el er
Eq Foo where
(A l) == (A r) = l == r
(B l) == (B r) = zipWithFoldrElem l r (f l r) (&&) True False False
where f : (ls : List Foo) -> (rs : List Foo) -> (l : Foo) -> (r : Foo) -> Elem (l, r) (zip ls rs) -> Bool
f (l :: _) (r :: _) l r Here = l == r
f (_ :: ls) (_ :: rs) l r (There e) = f ls rs l r e
f [] [] _ _ _ impossible
_ == _ = False
And, for show, here's a lexicographic Ord:
Ord Foo where
compare (A l) (A r) = l `compare` r
compare (B l) (B r) = zipWithFoldrElem l r (f l r) thenCompare EQ LT GT
where f : (ls : List Foo) -> (rs : List Foo) -> (l : Foo) -> (r : Foo) -> Elem (l, r) (zip ls rs) -> Ordering
f (l :: _) (r :: _) l r Here = l `compare` r
f (_ :: ls) (_ :: rs) l r (There e) = f ls rs l r e
f [] [] _ _ _ impossible
compare (A _) (B _) = LT
compare (B _) (A _) = GT
There's a much nicer way, now that I've grokked WellFounded a bit.
This data type is to Foo as Elem is to List. It tells you where to find a sub-Foo in a Foo.
-- s is smaller than b if either ...
data Smaller : (s : Foo) -> (b : Foo) -> Type where
-- it is one of the elements of ss when b = B ss
Surface : Elem s ss -> Smaller s (B ss)
-- it is smaller than one of the elements of ms when b = B ms
-- "m" is for "medium"
Deeper : Smaller s m -> Elem m ms -> Smaller s (B ms)
Smaller is WellFounded:
WellFounded Smaller where
wellFounded x = Access (acc x)
where mutual
acc : (b : Foo) -> (s : Foo) -> Smaller s b -> Accessible Smaller s
acc (B ss) s (Surface e) = accSurface ss s e
acc (B ms) s (Deeper {m} sr e) = accDeeper ms m e s sr
accSurface : (ss : List Foo) -> (s : Foo) -> Elem s ss -> Accessible Smaller s
accSurface (s :: _) s Here = Access (acc s)
accSurface (_ :: ss) s (There e) = accSurface ss s e
accDeeper : (ms : List Foo) -> (m : Foo) -> Elem m ms -> (s : Foo) -> Smaller s m -> Accessible Smaller s
accDeeper (m :: _) m Here s sr = acc m s sr
accDeeper (_ :: ms) m (There e) s sr = accDeeper ms m e s sr
This uses mutual recursion, just like my older answer, but it abstracts it away much more cleanly. The general skeleton of a WellFounded instance is:
WellFounded (rel : a -> a -> Type) where -- rel s b means s is smaller than b
wellFounded x = Access (acc x)
where acc : (b : a) -> (s : a) -> rel s b -> Accessible rel s
-- Accessible is really cryptic:
-- Access : (rec : (y : a) -> rel y x -> Accessible rel y) -> Accessible rel x
-- but the idea of acc is simple:
-- we convince the totality checker s is really smaller than b
-- acc needs to be recursive, and when it convinces the totality
-- checker, it can end with Access (acc s)
WellFounded buys us
wfRec : WellFounded rel =>
(step : (x : a) ->
(rec : (y : a) -> rel y x -> b) ->
b
) ->
a -> b
step is a function defined by open recursion. step gets an argument rec, and, instead of recursing to itself, step calls rec with a proof that the argument it's recursing on is the right size, and wfRec routes the call back to step (essentially it's fix : (step : (rec : (a -> b)) -> (x : a) -> b) -> a -> b; fix f x = f (fix f) x but total.)
We can now, cleanly, factor out the logic of (==) on lists:
eqBy : (ls : List a) -> (rs : List a) -> ((l : a) -> (r : a) -> (el : Elem l ls) -> (er : Elem r rs) -> Bool) -> Bool
eqBy (l :: ls) (r :: rs) eq = eq l r Here Here && eqBy ls rs (\l, r, el, er => eq l r (There el) (There er))
eqBy [] [] _ = True
eqBy _ _ _ = False
And the Eq instance is not much worse than the naive one:
Eq Foo where
(==) = wfRec step
where step : (x : Foo) -> ((y : Foo) -> Smaller y x -> Foo -> Bool) -> Foo -> Bool
step (A l) _ (A r) = l == r
step (B l) rec (B r) = eqBy l r (\l, r, el, er => rec l (Surface el) r)
step _ _ _ = False
eqBy and the WellFounded instance are now much more reusable than the zipWithFoldrElem abomination I previously created.
Lets say I have the following
data Expr : Type -> Type where
Lift : a -> Expr a
Add : Num a => Expr a -> Expr a -> Expr a
Cnst : Expr a -> Expr b -> Expr a
data Context : Type -> Type where
Root : Context ()
L : Expr w -> Context x -> Expr y -> Expr z -> Context w
R : Expr w -> Context x -> Expr y -> Expr z -> Context w
M : Expr w -> Context x -> Expr y -> Expr z -> Context w
data Zipper : Type -> Type -> Type where
Z : Expr f -> Context g -> Zipper f g
E : String -> Context g -> Zipper String ()
I would like to write a function to rebuild a Zipper if I'm going up one level in the expression tree. Something like:
total
ZipUp : Zipper focus parent -> Type
ZipUp (Z e (R (Cnst {a} e1 e2) {x} c t u)) = Zipper a x
ZipUp (Z {f} e (L (Cnst l r) {x} c t u)) = Zipper f x
ZipUp (Z e (R (Add {a} e1 e2) {x} c t u)) = Zipper a x
ZipUp (Z {f} e (L (Add e1 e2) {x} c t u)) = Zipper f x
ZipUp _ = Zipper String ()
the problem comes when I want to write the function to return a ZipUp
up : (x : Zipper focus parent) -> ZipUp x
up (Z e (R (Cnst l r) c x y)) = Z (Cnst l e) c
up (Z e (L (Cnst l r) c x y)) = Z (Cnst e r) c
up (Z e (R (Add l r) c x y)) = Z (Add l e) c
up (Z e (L (Add l r) c x y)) = Z (Add e r) c
up (Z e (R (Lift x) c l r)) = E "Some error" c
up (Z e (L (Lift x) c l r)) = E "Some error" c
up (E s c) = E s c
This fails to typecheck on the Add case, because it can't infer that focus (type of e) matches with parent (expected type)
So my question has two parts then.
What can I do to express this relationship?
(that if the Zipper is an R constructed, e has the same type as r, or that e has the same type as l in the L constructed case. I've tried using {e = l} and other variants of this, but to no avail.)
The the code typechecks and runs if I comment out the last for lines of up to finish with:
up : (x : Zipper focus parent) -> ZipUp x
up (Z e (R (Cnst l r) c x y)) = Z (Cnst l e) c
up (Z e (L (Cnst l r) c x y)) = Z (Cnst e r) c
but the actual manipulation of the types should be the same in the Add case, yet this fails to typecheck, why is that?
Thanks for taking the time to read and/or answer!
This fails to typecheck on the Add case, because it can't infer that focus (type of e) matches with parent (expected type)
Because this is not always the case, e.g.
*main> :t Z (Lift "a") (R (Add (Lift 1) (Lift 2)) Root (Lift 4) (Lift 8))
Z (Lift "a") (R (Add (Lift 1) (Lift 2)) Root (Lift 4) (Lift 8)) : Zipper String Integer
And Add (Lift 1) (Lift "a") doesn't work because of the Num a constraint.
What can I do to express this relationship?
If you want to express the relationship within up: You have e : Expr f and can say that the same f should be used in the Add case:
up (Z {f} e (R (Add l r {a=f}) c x y)) = Z (Add l e) c
up (Z {f} e (L (Add l r {a=f}) c x y)) = Z (Add e r) c
up (Z e (R (Add l r) c x y)) = ?whattodo_1
up (Z e (L (Add l r) c x y)) = ?whattodo_2
Now you have a non total function because of the cases where a != f. I don't quite what you want to do, so I can't offer an option. :-)
If you want to express the relationship in Zipper you could do (very roughly) something like:
data Context : Bool -> Type -> Type where
Root : Context False ()
L : Expr w -> Context b x -> Expr y -> Expr z -> Context False w
R : Expr w -> Context b x -> Expr y -> Expr z -> Context True w
M : Expr w -> Context b x -> Expr y -> Expr z -> Context False w
data Zipper : Type -> Type -> Type where
Z : Expr f -> Context False g -> Zipper f g
ZR : Expr f -> Context True f -> Zipper f f
E : String -> Context b g -> Zipper String ()
Now you construct a proof when building up a zipper that f = g in a R-Context. Again, I cannot be specific, but I hope it helps in some way.
In Idris, if I want to remove an element based on predicate, there is filter, dropWhile, takeWhile. However, all these functions return a dependent pair (n : Nat ** Vect n elem).
Is there any function that return back as a Vect type?
For what I could think of:
Convert a dependent pair to Vect
Implement a type that indicate the length vector after transformation (thought I have no idea how), like Here, There
For above ideas, it seems quite cumbersome for 1 (convert every result) or 2 (design each of the type to indicate the result vector length).
Are there any better ways to achieve such behaviour?
dropElem : String -> Vect n String -> Vect ?resultLen String
Maybe this is what you are searching for?
import Data.Vect
count: (ty -> Bool) -> Vect n ty -> Nat
count f [] = 0
count f (x::xs) with (f x)
| False = count f xs
| True = 1 + count f xs
%hint
countLemma: {v: Vect n ty} -> count f v `LTE` n
countLemma {v=[]} = LTEZero
countLemma {v=x::xs} {f} with (f x)
| False = lteSuccRight countLemma
| True = LTESucc countLemma
filter: (f: ty -> Bool) -> (v: Vect n ty) -> Vect (count f v) ty
filter f [] = []
filter f (x::xs) with (f x)
| False = filter f xs
| True = x::filter f xs
Then you con do this:
dropElem: (s: String) -> (v: Vect n String) -> Vect (count ((/=) s) v) String
dropElem s = filter ((/=) s)
You can even reuse the existing filter implementation:
count: (ty -> Bool) -> Vect n ty -> Nat
count f v = fst $ filter f v
filter: (f: ty -> Bool) -> (v: Vect n ty) -> Vect (count f v) ty
filter f v = snd $ filter f v
I'm very new to Idris (and dependent types). I was trying to do write a program to check if a string is a palindrome of not. To do that, I decided to compute the length of the string, and compute
q,r = (strlen `div` 2, strlen `mod` 2)
and then split the string as follows:
lhalf,rhalf = (substr 0 (q+r) str, substr (q-r) (q+r) str)
This takes care of both odd and even length strings. The problem is that Idris needs a proof that r < q since both q and r are Nat.
My question is: How do I express the fact that r
Here's the full sample of my code:
module Main
isPalindrome : (str : String) -> String
isPalindrome str =
let split = half_half str
in show ((fst split) == reverse (snd split))
where
strlen : Nat
strlen = length str
divMod : Nat -> Nat -> (Nat,Nat)
divMod x y = (x `div` y, x `mod` y)
half_half : String -> (String, String)
half_half "" = ("","")
half_half x = let
(q,r) = divMod strlen 2
in
(substr 0 (q+r) x,
substr (q-r) (q+r) x)
main : IO ()
main = repl "> " isPalindrome
You can't proof that r ≤ q because it's not true. For example, given the string "a" you have strlen = 1 and therefore q = 0 and r = 1. In this example r ≤ q is clearly false.
Note that you can implement isPalindrome simply by
isPalindrome: String -> Bool
isPalindrome str = str == reverse str