-
Notifications
You must be signed in to change notification settings - Fork 381
/
Copy pathElem.idr
101 lines (83 loc) · 3.25 KB
/
Elem.idr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
module Data.List.Elem
import Data.Singleton
import Decidable.Equality
import Control.Function
%default total
--------------------------------------------------------------------------------
-- List membership proof
--------------------------------------------------------------------------------
||| A proof that some element is found in a list.
public export
data Elem : a -> List a -> Type where
||| A proof that the element is at the head of the list
Here : Elem x (x :: xs)
||| A proof that the element is in the tail of the list
There : Elem x xs -> Elem x (y :: xs)
export
Uninhabited (Here {x} {xs} = There {x = x'} {y} {xs = xs'} e) where
uninhabited Refl impossible
export
Uninhabited (There {x} {y} {xs} e = Here {x = x'} {xs = xs'}) where
uninhabited Refl impossible
export
Injective (There {x} {y} {xs}) where
injective Refl = Refl
export
DecEq (Elem x xs) where
decEq Here Here = Yes Refl
decEq (There this) (There that) = decEqCong $ decEq this that
decEq Here (There later) = No absurd
decEq (There later) Here = No absurd
export
Uninhabited (Elem {a} x []) where
uninhabited Here impossible
uninhabited (There p) impossible
export
Uninhabited (x = z) => Uninhabited (Elem z xs) => Uninhabited (Elem z $ x::xs) where
uninhabited Here @{xz} = uninhabited Refl @{xz}
uninhabited (There y) = uninhabited y
||| An item not in the head and not in the tail is not in the list at all.
export
neitherHereNorThere : Not (x = y) -> Not (Elem x xs) -> Not (Elem x (y :: xs))
neitherHereNorThere xny _ Here = xny Refl
neitherHereNorThere _ xnxs (There xxs) = xnxs xxs
||| Check whether the given element is a member of the given list.
public export
isElem : DecEq a => (x : a) -> (xs : List a) -> Dec (Elem x xs)
isElem x [] = No absurd
isElem x (y :: xs) with (decEq x y)
isElem x (x :: xs) | Yes Refl = Yes Here
isElem x (y :: xs) | No xny with (isElem x xs)
isElem x (y :: xs) | No xny | Yes xxs = Yes (There xxs)
isElem x (y :: xs) | No xny | No xnxs = No (neitherHereNorThere xny xnxs)
||| Get the element at the given position.
public export
get : (xs : List a) -> (p : Elem x xs) -> a
get (x :: _) Here = x
get (_ :: xs) (There p) = get xs p
||| Get the element at the given position, with proof that it is the desired element.
public export
lookup : (xs : List a) -> (p : Elem x xs) -> Singleton x
lookup (x :: _) Here = Val x
lookup (_ :: xs) (There p) = lookup xs p
||| Remove the element at the given position.
public export
dropElem : (xs : List a) -> (p : Elem x xs) -> List a
dropElem (_ :: ys) Here = ys
dropElem (x :: ys) (There p) = x :: dropElem ys p
||| Erase the indices, returning the numeric position of the element
public export
elemToNat : Elem x xs -> Nat
elemToNat Here = Z
elemToNat (There p) = S (elemToNat p)
||| Find the element with a proof at a given position, if it is valid
public export
indexElem : Nat -> (xs : List a) -> Maybe (x ** Elem x xs)
indexElem _ [] = Nothing
indexElem Z (y :: _) = Just (y ** Here)
indexElem (S n) (_ :: ys) = map (\(x ** p) => (x ** There p)) (indexElem n ys)
||| Lift the membership proof to a mapped list
export
elemMap : (0 f : a -> b) -> Elem x xs -> Elem (f x) (map f xs)
elemMap f Here = Here
elemMap f (There el) = There $ elemMap f el