根据Typeclassopedia(以及其他来源),Applicative
逻辑上属于类型类层次结构中的Monad
和Pointed
(因此Functor
)之间,所以如果今天编写 Haskell 前奏,我们理想情况下会有这样的东西:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Pointed f where
pure :: a -> f a
class Pointed f => Applicative f where
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
-- either the traditional bind operation
(>>=) :: (m a) -> (a -> m b) -> m b
-- or the join operation, which together with fmap is enough
join :: m (m a) -> m a
-- or both with mutual default definitions
f >>= x = join ((fmap f) x)
join x = x >>= id
-- with return replaced by the inherited pure
-- ignoring fail for the purposes of discussion
(这些默认定义是我从维基百科的解释中重新输入的,错误是我自己的,但如果有错误,至少原则上是可能的。)
由于当前定义了库,因此我们有:
liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM :: (Monad m) => (a -> b) -> m a -> m b
和:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap :: (Monad m) => m (a -> b) -> m a -> m b
请注意每对中这些类型之间的相似性。
我的问题是:(liftM
与 不同liftA
)和ap
(与 不同<*>
)仅仅是没有考虑和Monad
设计的历史现实的结果吗?或者它们是否以某种其他行为方式(可能,对于某些法律定义)与只需要上下文的版本不同?Pointed
Applicative
Monad
Applicative
如果它们是不同的,您能否提供一组简单的定义(遵守 Typeclassopedia 和其他地方描述的、但未由类型系统强制执行的定义的法律)Monad
和行为不同?Applicative
Pointed
Functor
liftA
liftM
或者,如果它们不是不同的,您能否使用与前提相同的定律证明它们的等价性?