简体   繁体   中英

Non-empty-list comonad

I have been meditating on comonads and have an intuition that a non-empty list ("full list") is a comonad. I have constructed a plausible implementation in Idris and have worked on proving the comonad laws but have not been able to prove the recursive branch of one of the laws. How do I prove this (the ?i_do_not_know_how_to_prove_this_if_its_provable hole)--or am I wrong about my implementation being a valid comonad (I've looked at the Haskell NonEmpty comonad implementation and it seems to be the same as mine)?

module FullList

%default total

data FullList : Type -> Type where
  Single : a -> FullList a
  Cons : a -> FullList a -> FullList a

extract : FullList a -> a
extract (Single x) = x
extract (Cons x _) = x

duplicate : FullList a -> FullList (FullList a)
duplicate = Single 

extend : (FullList a -> b) -> FullList a -> FullList b
extend f (Single x) = Single (f (Single x))
extend f (Cons x y) = Cons (f (Cons x y)) (extend f y)

extend_and_extract_are_inverse : (l : FullList a) -> extend FullList.extract l = l
extend_and_extract_are_inverse (Single x) = Refl
extend_and_extract_are_inverse (Cons x y) = rewrite extend_and_extract_are_inverse y in Refl

comonad_law_1 : (l : FullList a) -> extract (FullList.extend f l) = f l
comonad_law_1 (Single x) = Refl
comonad_law_1 (Cons x y) = Refl

nesting_extend : (l : FullList a) -> extend f (extend g l) = extend (\x => f (extend g x)) l
nesting_extend (Single x) = Refl
nesting_extend (Cons x y) = ?i_do_not_know_how_to_prove_this_if_its_provable

Notice that your goal is of the following form:

Cons (f (Cons (g (Cons x y)) (extend g y))) (extend f (extend g y)) =
Cons (f (Cons (g (Cons x y)) (extend g y))) (extend (\x1 => f (extend g x1)) y)

You basically need to prove that the tail parts are equal:

extend f (extend g y) = extend (\x1 => f (extend g x1)) y

But that is exactly what the induction hypothesis ( nesting_extend y ) says! Hence, the proof is quite trivial:

nesting_extend : (l : FullList a) -> extend f (extend g l) = extend (f . extend g) l
nesting_extend (Single x) = Refl
nesting_extend (Cons x y) = cong $ nesting_extend y

I used the congruence lemma cong :

cong : (a = b) -> f a = f b

which says that any function f maps equal terms into equal terms.

Here Idris infers that f is Cons (f (Cons (g (Cons xy)) (extend gy))) , where the f inside Cons refers to nesting_extend 's parameter f .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM