mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-19 09:12:34 +03:00
88 lines
2.9 KiB
Idris
88 lines
2.9 KiB
Idris
module Data.List1.Elem
|
|
|
|
import Data.List1
|
|
import Data.List.Elem
|
|
|
|
import Decidable.Equality
|
|
import Control.Function
|
|
|
|
%default total
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- List1 membership proof
|
|
--------------------------------------------------------------------------------
|
|
|
|
||| A proof that some element is found in a list.
|
|
public export
|
|
data Elem : a -> List1 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 (List1.Elem.Here = List1.Elem.There e) where
|
|
uninhabited Refl impossible
|
|
|
|
export
|
|
Uninhabited (List1.Elem.There e = List1.Elem.Here) where
|
|
uninhabited Refl impossible
|
|
|
|
export
|
|
Injective (List1.Elem.There {x} {y} {xs}) where
|
|
injective Refl = Refl
|
|
|
|
export
|
|
DecEq (List1.Elem.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 (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 : List1 a) -> Dec (List1.Elem.Elem x xs)
|
|
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)
|
|
|
|
||| Remove the element at the given position. Forgets that the list is
|
|
||| non-empty, since there is no guarantee that it will remain non-empty after
|
|
||| the removal.
|
|
public export
|
|
dropElem : (xs : List1 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 : Data.List1.Elem.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 : List1 a) -> Maybe (x ** Elem x xs)
|
|
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) -> List1.Elem.Elem x xs -> List1.Elem.Elem (f x) (map f xs)
|
|
elemMap f Here = Here
|
|
elemMap f (There el) = There $ elemMap f el
|
|
|