简体   繁体   English

适用:证明`纯f <*> x =纯(翻转($))<*> x <*>纯f`

[英]Applicative: Prove `pure f <*> x = pure (flip ($)) <*> x <*> pure f`

During my study of Typoclassopedia I encountered this proof, but I'm not sure if my proof is correct. 在我对Typoclassopedia的研究中,我遇到了这个证据,但我不确定我的证据是否正确。 The question is: 问题是:

One might imagine a variant of the interchange law that says something about applying a pure function to an effectful argument. 人们可能会想到交换法的一种变体,它说的是将纯函数应用于有效的论证。 Using the above laws, prove that: 使用上述法律,证明:

pure f <*> x = pure (flip ($)) <*> x <*> pure f

Where "above laws" points to Applicative Laws , briefly: 如果“上述法律”指向适用法律 ,请简要说明:

pure id <*> v = v -- identity law
pure f <*> pure x = pure (f x) -- homomorphism
u <*> pure y = pure ($ y) <*> u -- interchange
u <*> (v <*> w) = pure (.) <*> u <*> v <*> w -- composition

My proof is as follows: 我的证据如下:

pure f <*> x = pure (($) f) <*> x -- identical
pure f <*> x = pure ($) <*> pure f <*> x -- homomorphism
pure f <*> x = pure (flip ($)) <*> x <*> pure f -- flip arguments

The first two steps of your proof look fine, but the last step doesn't. 您的证明的前两个步骤看起来很好,但最后一步没有。 While the definition of flip allows you to use a law like: 虽然flip的定义允许您使用如下法则:

f a b = flip f b a

that doesn't mean: 这并不意味着:

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

In fact, this is false in general. 事实上,这一般是错误的。 Compare the output of these two lines: 比较这两行的输出:

pure (+) <*> [1,2,3] <*> [4,5]
pure (flip (+)) <*> [4,5] <*> [1,2,3]

If you want a hint, you are going to need to use the original interchange law at some point to prove this variant. 如果您需要提示,您将需要在某个时候使用原始的交换法来证明这种变体。

In fact, I found I had to use the homomorphism, interchange, and composition laws to prove this, and part of the proof was pretty tricky, especially getting the sections right --like ($ f) , which is different from (($) f) . 事实上,我发现我必须使用同态,交换和组合定律来证明这一点,并且部分证明非常棘手,尤其是使得部分正确 - 类似($ f) ,这与(($) f) ($ f)不同(($) f) It was helpful to have GHCi open to double-check that each step of my proof type checked and gave the right result. 让GHCi打开以仔细检查我的证明类型的每一步都检查并给出正确的结果是有帮助的。 (Your proof above type checks fine; it's just that the last step wasn't justified.) (您上面的证据类型检查正常;这只是最后一步没有合理性。)

> let f = sqrt
> let x = [1,4,9]
> pure f <*> x
[1.0,2.0,3.0]
> pure (flip ($)) <*> x <*> pure f
[1.0,2.0,3.0]
>

I ended up proving it backwards: 我最后向后证明了这一点:

pure (flip ($)) <*> x <*> pure f
    = (pure (flip ($)) <*> x) <*> pure f -- <*> is left-associative
    = pure ($ f) <*> (pure (flip ($)) <*> x) -- interchange
    = pure (.) <*> pure ($ f) <*> pure (flip ($)) <*> x -- composition
    = pure (($ f) . (flip ($))) <*> x -- homomorphism
    = pure (flip ($) f . flip ($)) <*> x -- identical
    = pure f <*> x

Explanation of the last transformation: 最后一次转换的解释:

flip ($) has type a -> (a -> c) -> c , intuitively, it first takes an argument of type a , then a function that accepts that argument, and in the end it calls the function with the first argument. flip ($)a -> (a -> c) -> c类型a -> (a -> c) -> c ,直观地说,它首先接受一个类型为a的参数,然后是一个接受该参数的函数,最后它用第一个参数调用该函数。 So flip ($) 5 takes as argument a function which gets called with 5 as it's argument. 因此, flip ($) 5将一个函数作为参数,该函数以5作为参数调用。 If we pass (+ 2) to flip ($) 5 , we get flip ($) 5 (+2) which is equivalent to the expression (+2) $ 5 , evaluating to 7 . 如果我们传递(+ 2)flip ($) 5 ,我们得到flip ($) 5 (+2) ,相当于表达式(+2) $ 5 ,评估为7

flip ($) f is equivalent to \\x -> x $ f , that means, it takes as input a function and calls it with the function f as argument. flip ($) f相当于\\x -> x $ f ,这意味着它将一个函数作为输入,并以函数f作为参数调用它。

The composition of these functions works like this: First flip ($) takes x as it's first argument, and returns a function flip ($) x , this function is awaiting a function as it's last argument, which will be called with x as it's argument. 这些函数的组成如下:第一个flip ($)x作为它的第一个参数,并返回一个函数flip ($) x ,这个函数正在等待函数作为它的最后一个参数,它将被调用x作为它的论点。 Now this function flip ($) x is passed to flip ($) f , or to write it's equivalent (\\x -> x $ f) (flip ($) x) , this results in the expression (flip ($) x) f , which is equivalent to f $ x . 现在这个函数flip ($) x被传递给flip ($) f ,或者写它的等价物(\\x -> x $ f) (flip ($) x) ,这导致表达式(flip ($) x) f ,相当于f $ x

You can check the type of flip ($) f . flip ($) 你可以检查flip ($) f . flip ($)的类型flip ($) f . flip ($) flip ($) f . flip ($) is something like this (depending on your function f ): flip ($) f . flip ($)是这样的(取决于你的函数f ):

λ: let f = sqrt
λ: :t (flip ($) f) . (flip ($))
(flip ($) f) . (flip ($)) :: Floating c => c -> c

I'd remark that such theorems are, as a rule, a lot less involved when written in mathematical style of a monoidal functor , rather than the applicative version, ie with the equivalent class 我会注意到这样的定理通常在用幺正函子的数学风格编写时很少涉及,而不是应用版本,即具有相同的类

class Functor f => Monoidal f where
  pure :: a -> f a
  (⑂) :: f a -> f b -> f (a,b)

Then the laws are 那么法律就是

id <$> v = v
f <$> (g <$> v) = f . g <$> v
f <$> pure x = pure (f x)
x ⑂ pure y = fmap (,y) x
a⑂(b⑂c) = assoc <$> (a⑂b)⑂c

where assoc ((x,y),z) = (x,(y,z)) . 其中assoc ((x,y),z) = (x,(y,z))

The theorem then reads 该定理然后读

pure u ⑂ x = swap <$> x ⑂ pure u

Proof: 证明:

swap <$> x ⑂ pure u
    = swap <$> fmap (,u) x
    = swap . (,u) <$> x
    = (u,) <$> x
    = pure u ⑂ x

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

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