简体   繁体   English

证明流的平等

[英]Proving equality of streams

I have a data type 我有一个数据类型

data N a = N a [N a]

of rose trees and Applicative instance 玫瑰树和应用实例

instance Applicative N where
 pure a = N a (repeat (pure a))
 (N f xs) <*> (N a ys) = N (f a) (zipWith (<*>) xs ys)

and need to prove the Applicative laws for it. 并需要证明适用法律。 However, pure creates infinitely deep, infinitely branching trees. 然而, 纯粹创造无限深,无限分枝的树木。 So, for instance, in proving the homomorphism law 因此,例如,在证明同态定律

pure f <*> pure a = pure (f a)

I thought that proving the equality 我认为这证明了平等

zipWith (<*>) (repeat (pure f)) (repeat (pure a)) = repeat (pure (f a))

by the approximation (or take) lemma would work. 通过近似(或采取)引理将起作用。 However, my attempts lead to "vicious circles" in the inductive step. 然而,我的尝试导致归纳步骤中的“恶性循环”。 In particular, reducing 特别是减少

approx (n + 1) (zipWith (<*>) (repeat (pure f)) (repeat (pure a))

gives

(pure f <*> pure a) : approx n (repeat (pure (f a)))

where approx is the approximation function. 其中approx是近似函数。 How can I prove the equality without an explicit coinductive proof? 如果没有明确的共同证据,我怎样才能证明这种平等?

I'd use the universal property of unfolds (since repeat and a suitably uncurried zipWith are both unfolds). 我会使用展开的通用属性(因为重复和适当的不合格的拉链都展开)。 There's a related discussion on my blog . 在我的博客上有一个相关的讨论。 But you might also like Ralf Hinze's papers on unique fixpoints ICFP2008 (and the subsequent JFP paper). 但您可能也喜欢Ralf Hinze关于ICFP2008 (以及随后的JFP论文)的独特定点的论文。

(Just checking: all your rose trees are infinitely wide and infinitely deep? I'm guessing that the laws won't hold otherwise.) (只是检查一下:你所有的玫瑰树都是无限宽而且无限深?我猜这些法律不会另有规定。)

The following is a sketch of something that I think works and remains at the level of programmatic syntax and equational reasoning. 以下是我认为有用并且保持在程序语法和等式推理层面的一些草图。

The basic intuition is that it is much easier to reason about repeat x than it is to reason about a stream (and worse yet, a list) in general. 基本的直觉是, repeat x推理要比推理流(更糟糕的是,列表)更容易。

uncons (repeat x) = (x, repeat x)

zipWithAp xss yss = 
    let (x,xs) = uncons xss
        (y,ys) = uncons yss
    in (x <*> y) : zipWithAp xs ys

-- provide arguments to zipWithAp
zipWithAp (repeat x) (repeat y) = 
    let (x',xs) = uncons (repeat x)
        (y',ys) = uncons (repeat y)
    in (x' <*> y') : zipWithAp xs ys

-- substitute definition of uncons...
zipWithAp (repeat x) (repeat y) = 
    let (x,repeat x) = uncons (repeat x)
        (y,repeat y) = uncons (repeat y)
    in (x <*> y) : zipWithAp (repeat x) (repeat y)

-- remove now extraneous let clause
zipWithAp (repeat x) (repeat y) = (x <*> y) : zipWithAp (repeat x) (repeat y)

-- unfold identity by one step
zipWithAp (repeat x) (repeat y) = (x <*> y) : (x <*> y) : zipWithAp (repeat x) (repeat y)

-- (co-)inductive step
zipWithAp (repeat x) (repeat y) = repeat (x <*> y)

Why do yo need coinduction? 你为什么需要共同诱导? Just induct. 只是归纳。

pure f <*> pure a = pure (f a)

can also be written (you need to prove the left and right equality) 也可以写(你需要证明左右相等)

N f [(pure f)] <*> N a [(pure a)] = N (f a) [(pure (f a))]

which allows you to off one term at a time. 这允许你一次关闭一个学期。 That gives you your induction. 这会给你感应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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