[英]Applicative: Prove `pure f <*> x = pure (flip ($)) <*> x <*> pure f`
在我对Typoclassopedia的研究中,我遇到了这个证据,但我不确定我的证据是否正确。 问题是:
人们可能会想到交换法的一种变体,它说的是将纯函数应用于有效的论证。 使用上述法律,证明:
pure f <*> x = pure (flip ($)) <*> x <*> pure f
如果“上述法律”指向适用法律 ,请简要说明:
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
我的证据如下:
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
您的证明的前两个步骤看起来很好,但最后一步没有。 虽然flip
的定义允许您使用如下法则:
f a b = flip f b a
这并不意味着:
pure f <*> a <*> b = pure (flip f) <*> b <*> a
事实上,这一般是错误的。 比较这两行的输出:
pure (+) <*> [1,2,3] <*> [4,5]
pure (flip (+)) <*> [4,5] <*> [1,2,3]
如果您需要提示,您将需要在某个时候使用原始的交换法来证明这种变体。
事实上,我发现我必须使用同态,交换和组合定律来证明这一点,并且部分证明非常棘手,尤其是使得部分正确 - 类似($ f)
,这与(($) f)
($ f)
不同(($) f)
。 让GHCi打开以仔细检查我的证明类型的每一步都检查并给出正确的结果是有帮助的。 (您上面的证据类型检查正常;这只是最后一步没有合理性。)
> 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]
>
我最后向后证明了这一点:
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
最后一次转换的解释:
flip ($)
有a -> (a -> c) -> c
类型a -> (a -> c) -> c
,直观地说,它首先接受一个类型为a
的参数,然后是一个接受该参数的函数,最后它用第一个参数调用该函数。 因此, flip ($) 5
将一个函数作为参数,该函数以5
作为参数调用。 如果我们传递(+ 2)
到flip ($) 5
,我们得到flip ($) 5 (+2)
,相当于表达式(+2) $ 5
,评估为7
。
flip ($) f
相当于\\x -> x $ f
,这意味着它将一个函数作为输入,并以函数f
作为参数调用它。
这些函数的组成如下:第一个flip ($)
将x
作为它的第一个参数,并返回一个函数flip ($) x
,这个函数正在等待函数作为它的最后一个参数,它将被调用x
作为它的论点。 现在这个函数flip ($) x
被传递给flip ($) f
,或者写它的等价物(\\x -> x $ f) (flip ($) x)
,这导致表达式(flip ($) x) f
,相当于f $ x
。
你可以检查flip ($) f . flip ($)
的类型flip ($) f . flip ($)
flip ($) f . flip ($)
是这样的(取决于你的函数f
):
λ: let f = sqrt
λ: :t (flip ($) f) . (flip ($))
(flip ($) f) . (flip ($)) :: Floating c => c -> c
我会注意到这样的定理通常在用幺正函子的数学风格编写时很少涉及,而不是应用版本,即具有相同的类
class Functor f => Monoidal f where
pure :: a -> f a
(⑂) :: f a -> f b -> f (a,b)
那么法律就是
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
其中assoc ((x,y),z) = (x,(y,z))
。
该定理然后读
pure u ⑂ x = swap <$> x ⑂ pure u
证明:
swap <$> x ⑂ pure u
= swap <$> fmap (,u) x
= swap . (,u) <$> x
= (u,) <$> x
= pure u ⑂ x
□
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.