" ap"是多么武断的monads的实现?

时间:2015-09-28 13:10:41

标签: haskell monads applicative

我目前正在研究monad和applicative functors之间的关系。

我看到ap的两个实现:

ap m1 m2 = do { f <- m1 ; x <- m2 ; return (f x) }

ap m1 m2 = do { x <- m2 ; f <- m1 ; return (f x) }

第二个是不同的,但它是<*>的一个很好的实现吗?

我迷失在pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

的证据中

我试图直观地了解&#34; monad的哪一部分是应用函子&#34; ...

2 个答案:

答案 0 :(得分:17)

这个问题至少有三个相关方面。

  1. 给定一个Monad m实例,其必要的Applicative m超类实例的规范是什么? 答案purereturn<*>ap,所以

    mf <*> ms == do f <- mf; s <- ms; return (f s)
    
  2. 请注意,此规范不是Applicative类的法则。这是Monad的要求,以确保一致的使用模式。

    1. 鉴于该规范(通过候选实现),ap是唯一可接受的实现。 回答:响亮,没有>>=类型允许的值依赖性有时会导致执行效率低下:在某些情况下,<*>可以比ap更高效,因为您不需要等待在你可以告诉第二次计算是什么之前完成第一次计算。 &#34;应用程序&#34;记谱法确实存在于利用这种可能性。

    2. Applicative的任何其他候选实例是否满足Applicative法律,即使他们不同意所需的ap实例? 回答:是的。 &#34;向后&#34;问题提出的实例就是这样的事情。事实上,正如另一个答案所指出的那样,任何一个应用都可以倒退,结果通常是不同的野兽。

    3. 对于读者的进一步示例和练习,请注意非空列表是普通列表中熟悉的单词。

        data Nellist x = x :& Maybe (Nellist x)
      
        necat :: Nellist x -> Nellist x -> Nellist x
        necat (x :& Nothing) ys = x :& Just ys
        necat (x :& Just xs) ys = x :& Just (necat xs ys)
      
        instance Monad Nellist where
          return x = x :& Nothing
          (x :& Nothing) >>= k = k x
          (x :& Just xs) >>= k = necat (k x) (xs >>= k)
      

      至少找到符合适用法律的四个行为不同的Applicative Nellist实例。

答案 1 :(得分:6)

让我们从一个显而易见的事实开始:IsEmail这样的定义违反了<*>法律,ap <*> ap应该apMonadap类中定义的那个,即您发布的第一个。

除了琐事之外,据我所知,其他适用法律应该成立。

更具体地说,让我们关注你提到的构成法。 你的“逆转”(<**>) m1 m2 = do { x <- m2 ; f <- m1 ; return (f x) }

(<**>) m1 m2 = pure (flip ($)) <*> m2 <*> m1

也可以定义为

<*>

其中ap是“常规”u <**> (v <**> w) = { def. <**> } pure (flip ($)) <*> (v <**> w) <*> u = { def. <**> } pure (flip ($)) <*> (pure (flip ($)) <*> w <*> v) <*> u = { composition law } pure (.) <*> pure (flip ($)) <*> (pure (flip ($)) <*> w) <*> v <*> u = { homomorphism law } pure ((.) (flip ($))) <*> (pure (flip ($)) <*> w) <*> v <*> u = { composition law } pure (.) <*> pure ((.) (flip ($))) <*> pure (flip ($)) <*> w <*> v <*> u = { homomorphism law (x2)} pure ((.) ((.) (flip ($))) (flip ($))) <*> w <*> v <*> u = { beta reduction (several) } pure (\x f g -> g (f x)) <*> w <*> v <*> u

这意味着,例如,

pure (.) <**> u <**> v <**> w = ...

(我希望我能把一切都搞定)

尝试做类似于左手边的事情。

for i in range(100):
    if i%(2*n) < n :
        fun1()
    else:
        fun2()