非空列表comonad
Non-empty-list comonad
我一直在思考 comonad,直觉认为非空列表 ("full list") 是一个 comonad。我在 Idris 中构建了一个合理的实现,并致力于证明 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 实现,它似乎与我的相同)?
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
请注意,您的目标具有以下形式:
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)
你基本上需要证明尾部相等:
extend f (extend g y) = extend (\x1 => f (extend g x1)) y
但这正是归纳假设 (nesting_extend y
) 所说的!因此,证明非常简单:
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
我使用了同余引理cong
:
cong : (a = b) -> f a = f b
表示任何函数 f
将等项映射为等项。
这里Idris推断f
是Cons (f (Cons (g (Cons x y)) (extend g y)))
,其中Cons
里面的f
指的是nesting_extend
的参数f
。
我一直在思考 comonad,直觉认为非空列表 ("full list") 是一个 comonad。我在 Idris 中构建了一个合理的实现,并致力于证明 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 实现,它似乎与我的相同)?
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
请注意,您的目标具有以下形式:
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)
你基本上需要证明尾部相等:
extend f (extend g y) = extend (\x1 => f (extend g x1)) y
但这正是归纳假设 (nesting_extend y
) 所说的!因此,证明非常简单:
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
我使用了同余引理cong
:
cong : (a = b) -> f a = f b
表示任何函数 f
将等项映射为等项。
这里Idris推断f
是Cons (f (Cons (g (Cons x y)) (extend g y)))
,其中Cons
里面的f
指的是nesting_extend
的参数f
。