Sri*_*aic 14 haskell applicative semigroup
给定一个操作(??)
,使得
(a ?? b) ?? c = a ?? (b ?? c)
Run Code Online (Sandbox Code Playgroud)
(也就是说(??)
是联想的)
一定是这样
liftA2 (??) (liftA2 (??) a b) c = liftA2 (??) a (liftA2 (??) b c)
Run Code Online (Sandbox Code Playgroud)
(也就是说liftA2 (??)
是联想的)
如果我们愿意,我们可以将其重写为:
fmap (??) (fmap (??) a <*> b) <*> c = fmap (??) a <*> (fmap (??) b <*> c)
Run Code Online (Sandbox Code Playgroud)
我花了一点时间盯着适用的法律,但我无法拿出证据证明情况确实如此。所以我开始反驳它。我尝试过的所有开箱即用的应用程序(Maybe
、[]
、Either
等)都遵循法律,所以我想我会创建自己的应用程序。
我最好的想法是制作一个空的应用程序,并附加一条额外的信息。
data Vacuous a = Vac Alg
Run Code Online (Sandbox Code Playgroud)
Alg
我稍后会在自己方便的时候定义哪些代数可以使财产失败但适用的法律成功。
现在我们这样定义我们的实例:
instance Functor Vacuous where
fmap f = id
instance Applicative Vacuous where
pure x = Vac i
liftA2 f (Vac a) (Vac b) = Vac (comb a b)
(Vac a) <*> (Vac b) = Vac (comb a b)
Run Code Online (Sandbox Code Playgroud)
哪里i
是Alg
待确定的某个元素,并且comb
是一个二元组合器Alg
也待确定。我们真的没有其他方法可以定义这一点。
如果我们想要满足Identity定律,这将强制i
成为一个 identity over comb
。然后我们免费获得同态和交换。但是现在Composition强制comb
关联Alg
((pure (.) <*> Vac u) <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
((Vac i <*> Vac u) <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
(Vac u <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
(Vac (comb u v)) <*> Vac w = Vac u <*> (Vac (comb v w))
Vac (comb (comb u v) w) = Vac (comb u (comb v w))
comb (comb u v) w = comb u (comb v w)
Run Code Online (Sandbox Code Playgroud)
迫使我们满足财产。
有反例吗?如果不是,我们如何证明这个属性?
我们首先使用应用定律重写左侧。回想一下,<$>
and<*>
都是左结合的,所以我们有,例如,x <*> y <*> z = (x <*> y) <*> z
and x <$> y <*> z = (x <$> y) <*> z
。
(??) <$> ((??) <$> a <*> b) <*> c
= fmap/pure law
pure (??) <*> (pure (??) <*> a <*> b) <*> c
= composition law
pure (.) <*> pure (??) <*> (pure (??) <*> a) <*> b <*> c
= homomorphism law
pure ((.) (??)) <*> (pure (??) <*> a) <*> b <*> c
= composition law
pure (.) <*> pure ((.) (??)) <*> pure (??) <*> a <*> b <*> c
= homomorphism law
pure ((.) ((.) (??)) (??)) <*> a <*> b <*> c
= definition (.)
pure (\x -> (.) (??) ((??) x)) <*> a <*> b <*> c
= definition (.), eta expansion
pure (\x y z -> (??) ((??) x y) z) <*> a <*> b <*> c
= associativity (??)
pure (\x y z -> x ?? y ?? z) <*> a <*> b <*> c
Run Code Online (Sandbox Code Playgroud)
最后一种形式表明,从本质上讲,原始表达式“运行”动作a
、b
,并c
以该顺序,以这种方式对它们的效果进行排序,然后用于(??)
纯粹地组合三个结果。
然后我们可以证明右手边等价于上面的形式。
(??) <$> a <*> ((??) <$> b <*> c)
= fmap/pure law
pure (??) <*> a <*> (pure (??) <*> b <*> c)
= composition law
pure (.) <*> (pure (??) <*> a) <*> (pure (??) <*> b) <*> c
= composition law
pure (.) <*> pure (.) <*> pure (??) <*> a <*> (pure (??) <*> b) <*> c
= homomorphism law
pure ((.) (.) (??)) <*> a <*> (pure (??) <*> b) <*> c
= composition law
pure (.) <*> (pure ((.) (.) (??)) <*> a) <*> pure (??) <*> b <*> c
= composition law
pure (.) <*> pure (.) <*> pure ((.) (.) (??)) <*> a <*> pure (??) <*> b <*> c
= homomorphism law
pure ((.) (.) ((.) (.) (??))) <*> a <*> pure (??) <*> b <*> c
= interchange law
pure ($ (??)) <*> (pure ((.) (.) ((.) (.) (??))) <*> a) <*> b <*> c
= composition law
pure (.) <*> pure ($ (??)) <*> pure ((.) (.) ((.) (.) (??))) <*> a <*> b <*> c
= homomorphism law
pure ((.) ($ (??)) ((.) (.) ((.) (.) (??)))) <*> a <*> b <*> c
Run Code Online (Sandbox Code Playgroud)
现在,我们只需要以((.) ($ (??)) ((.) (.) ((.) (.) (??))))
更易读的有点形式重写无点项,这样我们就可以使它等于我们在证明的前半部分得到的项。这只是申请(.)
和($)
需要的问题。
((.) ($ (??)) ((.) (.) ((.) (.) (??))))
= \x -> (.) ($ (??)) ((.) (.) ((.) (.) (??))) x
= \x -> ($ (??)) ((.) (.) ((.) (.) (??)) x)
= \x -> (.) (.) ((.) (.) (??)) x (??)
= \x y -> (.) ((.) (.) (??) x) (??) y
= \x y -> (.) (.) (??) x ((??) y)
= \x y z -> (.) ((??) x) ((??) y) z
= \x y z -> (??) x ((??) y z)
= \x y z -> x ?? y ?? z
Run Code Online (Sandbox Code Playgroud)
在最后一步中,我们利用了 的结合性(??)
。
(呸。)