使 Applicative 成为 Monad 所需的“最低限度”是多少?

Nic*_*oux 16 monads haskell functional-programming category-theory applicative

Monad类型类可以来定义return(>>=)。然而,如果我们已经有一个Functor实例针对某些类型的构造函数f,那么这个定义是有点“比我们更需要”在(>>=)return可以用来实现fmap,所以我们赚不到使用的Functor,我们假设实例。

相比之下,定义returnjoin似乎是一个更“最小” /更少冗余的方式,使f一个Monad。这样,Functor约束是必不可少的,因为fmap不能根据这些操作来编写。(注意join不一定是从Functor到的唯一最小方法Monad:我认为(>=>)也有效。)

类似地,Applicative可以用pure和来定义(<*>),但是这个定义同样没有利用Functor约束,因为这些操作足以定义fmap

但是,Applicative f也可以使用unit :: f ()和来定义(>*<) :: f a -> f b -> f (a, b)。这些操作不足以定义,fmap所以我会说从某种意义上说这是从Functor到的更简单的方法Applicative

是否有Monadas fmapunit(>*<)和其他一些最小的运算符的特征,因为这些函数都不能从其他函数派生出来?

  • (>>=)不起作用,因为它可以实现a >*< b = a >>= (\ x -> b >>= \ y -> pure (x, y))where pure x = fmap (const x) unit
  • 也不是join因为m >>= k = join (fmap k m)这样(>*<)可以如上实现。
  • 我怀疑(>=>)同样失败。

luq*_*qui 7

我有东西,我想。它远非优雅,但至少足以让你摆脱困境。我开始join :: m (m a) -> ???问“它会产生什么需要(<*>)返回m a?”,我发现这是一个富有成效的思路,可能有更多的战利品。

如果你引入一个T只能在 monad 内部构造的新类型:

t :: m T
Run Code Online (Sandbox Code Playgroud)

然后你可以定义一个类似连接的操作,它需要这样的T

joinT :: m (m a) -> m (T -> a)
Run Code Online (Sandbox Code Playgroud)

我们可以产生T我们需要获得甜蜜,甜蜜的a内部的唯一方法是使用t,然后我们必须将它与joinT某种方式的结果结合起来。有两种基本操作可以将两个ms合二为一:(<*>)joinT--fmap无济于事。 joinT不会工作,因为我们只需要另一个T来使用它的结果,所以(<*>)是唯一的选择,这意味着(<*>)不能用joinT.

如果您愿意,您可以将所有内容汇总为存在主义。

joinT :: (forall t. m t -> (m (m a) -> m (t -> a)) -> r) -> r
Run Code Online (Sandbox Code Playgroud)