为什么应用程序是Monad的超类?
鉴于:
Applicative m, Monad m => mf :: m (a -> b), ma :: ma 这似乎被认为是一个法律:
 mf <*> ma === do { f <- mf; a <- ma; return (fa) } 
或者更简洁:
 (<*>) === ap 
  Control.Applicative的文档说<*>是“顺序应用程序”,这表明(<*>) = ap 。 这意味着, <*>必须按顺序从左到右评估效果,与>>= …保持一致。但这种感觉是错误的。  McBride和Paterson的原始文件似乎意味着从左到右的sorting是任意的: 
IO monad,实际上任何Monad都可以通过使用
pure=return和<*>=ap。 我们也可以用相反顺序执行计算的ap的变体 ,但是在本文中我们应该保持从左到右的顺序。
 所以有两个合法的,不重要的派生出现在<*> >>=和return ,具有不同的行为。 而且在某些情况下,这两个派生都不可取。 
 例如, (<*>) === ap法则强制Data.Validation定义两个不同的数据types: Validation和AccValidation 。 前者具有类似于ExceptT的Monad实例,以及由于在第一个错误之后停止而具有有限效用的一致Applicative实例。 后者另一方面并没有定义Monad实例,因此可以自由地实现一个更有用的Applicative来积累错误。 
先前在StackOverflow上已经讨论过这个问题,但是我不认为它真的有问题:
为什么这应该是一个法律?
 函子,应用程序和monad的其他法则(如身份,关联等)表示这些结构的一些基本的math属性。 我们可以使用这些法则来实现各种优化,并使用它们来certificate我们自己的代码。 相反,我感觉像(<*>) === ap法则强加一个任意的约束,没有相应的好处。 
为了什么是值得的,我宁愿抛弃法律来支持这样的事情:
 newtype LeftA ma = LeftA (ma) instance Monad m => Applicative (LeftA m) where pure = return mf <*> ma = do { f <- mf; a <- ma; return (fa) } newtype RightA ma = RightA (ma) instance Monad m => Applicative (RightA m) where pure = return mf <*> ma = do { a <- ma; f <- mf; return (fa) } 
我认为这正确地捕捉了两者之间的关系,而没有不适当的约束。
所以,从以下几个angular度来处理这个问题:
-  还有其他法律有关Monad和Applicative?
-  是否有任何内在的math原因为Applicativesorting方式与Monad?
- GHC或任何其他工具是否执行代码转换,假定/要求这个法则是正确的?
- 为什么Functor-Applicative-Monad的提议认为这是一件非常好的事情? (引用在这里非常感谢)。
还有一个额外的问题:
-   Alternative和MonadPlus如何适应这一切?
注意:主要编辑澄清问题的肉。 回复@duplode引用了早期版本。
那么到目前为止,我对这个问题的答案并不是非常满意,但是我认为这些问题的意见更加引人注目。 所以我在这里总结一下:
 我认为只有一个明显的Functor实例来自Applicative : 
 fmap f fa = pure f <*> fa 
 假设它是独一无二的,那Functor应该成为Applicative的超类,这是有道理的。 同样,我认为Monad只有一个明显的Functor实例: 
 fmap f fa = fa >>= return . f 
 所以再说一次, Functor应该是Monad的超类。 我曾经(而且实际上还有)的反对意见是, Monad有两个明显的Applicative实例,在某些特定情况下,还有更多的合法实例; 那么为什么要求呢? 
  pigworker ( 原Applicative文件中的第一作者)写道: 
“当然不会,这是一个select。”
(在微博上 ):“记事是对单身工作的不公正惩罚,我们应该得到应用记法”
duplode同样写道:
“……可以肯定地说,
pure === return和(<*>) === ap在强烈的意义上并不是法律,例如monad法则是如此……”“在
LeftA/RightA思想中:在标准库的其他地方有类似的情况(例如,Data.MonoidSum和Product)。与Applicative相同的问题是,权重关系太低而不能certificate额外的精度/灵活性,新型将使应用风格使用起来不那么愉快。“
所以,我很高兴地看到这个select是明确陈述的,通过简单的推理certificate它使最常见的情况更容易。
 除此之外,你问为什么Functor-Applicative-Monadbuild议是好事。 原因之一是缺乏统一意味着API有很多重复。 考虑标准的Control.Monad模块。 以下是该模块中基本上使用Monad ( MonadPlus没有)限制的function: 
 (>>=) fail (=<<) (>=>) (<=<) join foldM foldM_ 
 以下是该模块中Monad / MonadPlus约束可以轻松应用于MonadPlus / Alternative : 
 (>>) return mzero mplus mapM mapM_ forM forM_ sequence sequence_ forever msum filterM mapAndUnzipM zipWithM zipWithM_ replicateM replicateM_ guard when unless liftM liftM2 liftM3 liftM4 liftM5 ap 
 后者中的许多组在Control.Applicative , Data.Foldable或Data.Traversable 都具有Applicative或Alternative版本,但是为什么首先需要了解所有的重复? 
并且在我自己的(也许是错误的)直觉中,给定
pure f <*> ma <*> mb,不需要任何预定的测序,因为这些值都不相互依赖。
 值不,但效果。  (<*>) :: t (a -> b) -> ta -> tb意味着您必须以某种方式组合参数的效果才能获得整体效果。 组合是否可交换取决于实例是如何定义的。 例如, Maybe的实例是可交换的,而列表的默认“交叉连接”实例不是。 因此,有些情况下你不能避免强加一些命令。 
Monad和Applicative有什么法律?
 虽然pure === return和(<*>) === ap (引用Control.Applicative )在公平的意义上并不是强制意义上的法律,例如monad法则是这样,它们有助于保持实例不令人吃惊。 鉴于每个Monad引起了Applicative一个实例(实际上是两个实例,正如你指出的那样),所以Applicative的实际实例与Monad给我们的实例是自然匹配的。 至于从左到右的约定,遵循ap和liftM2的顺序 (当Applicative被引入时已经存在,并且反映(>>=)强加的顺序)是一个明智的决定。  (注意,如果我们在实践中忽略了多less(>>=)事情,相反的select也是可以辩护的,因为它会使(<*>)和(=<<)具有类似的types,按相同的顺序排列效果。) 
GHC或任何其他工具是否执行代码转换,假定/要求这个法则是正确的?
 这听起来不太可能,因为Applicative甚至不是Monad的超类。 然而,这些“法律”允许守则的读者进行同样重要的转换。 
 注意:如果您需要在Applicative实例中反转效果sorting,那么就有Control.Applicative.Backwards ,就像Gabriel Gonzalez指出的那样。 另外, (<**>)翻转参数,但是仍然从左向右排列效果,所以它也可以用来反转sorting。 同样, (<*)不是flip (*>) ,因为这两个序列效果从左到右。 
只是为了logging,标题中的问题的答案是:考虑
 sequenceA :: Applicative f, Traversable t => t (fa) -> f (ta) join :: Monad m => m (ma) -> ma 
 什么是join . sequenceA的typesjoin . sequenceA  join . sequenceA ? 
-   ATP: Monad m, Traversable m => m (ma) -> ma
-  现状: Applicative m, Monad m, Traversable m => m (ma) -> ma
 授予, join . sequenceA  join . sequenceA是一个人为的情况,但是肯定有一些情况下你需要一个monad,但是你也想使用Applicative操作<*> , *> , <* , <**>等等。然后: 
- 有两个单独的约束来捕获这两个操作是令人讨厌的。
-   Applicative名称是(恕我直言)比传统的monad操作更好。
-  有两个不同的名字,例如ap,>>,<<等,是讨厌的(“哦,你不能在那里使用,这是Monad不是一个Applicative”;“哦,你必须使用<*>那里,这是一个Applicative不是一个Monad“)。
-  在真正的monad中,顺序是非常重要的,这意味着如果>>和*>做不同的事情,那么你实际上不能使用Applicative语法,因为它会做你不期望的事情。
 因此,务实地,对每一个与之兼容的Monad (在(<*>) = ap意义上)都是一个真正的好主意。