两个应用程序/单子程序都保持单曲面结构但以稍微不同的方式具有什么实际含义?

问题描述 投票:3回答:1

我已经读过Q&A,但不理解类别理论的一部分。

到目前为止,这是我的推理:当我查看类型时

F (a -> b) -> F a -> F b
(a -> M b) -> M a -> M b

a -> F a
a -> M a

在类型级别上唯一类似于一个monoid的部分是类型构造函数,即应用/单调上下文:

// binary operation
F -> F -> F
M -> M -> M

// identity element
F
M

因此,我认为应用程序/单子在上下文方面是单调的,因为它们将相同类型的两个上下文组合为一个。pure/ return创建了一个最小的上下文,因此我们可以将其视为与一个monoid的标识元素相似的身份上下文,从而创建一个“最大的最小值”。

但是,单子/应用程序的类型参数不是单项式的,因为它们包括从ab的转换。

我不确定我的推理是否有意义。让我感到困惑的是,一方面的类人独具一格的东西,另一方面,应用性/单子独一的结合方式则不同:

Nothing <> (Just "bar") -- Just "bar"
(++) <$> Nothing <*> (Just "bar") -- Nothing
Nothing >>= (\x -> (Just "bar") >>= (return . (++) x)) -- Nothing

但是,我猜想不同的结果值是由于等分体将表达式解释为普通值,而应用程序/ monads将表达式解释为计算(在上面的示例中可能会失败)。

[在前面的问答中,现在指出单子在内爆函子的类别中是单半体的,而施用物是松散的单半子函子。我不完全理解,但显然应用程序仅部分保留了单面体结构,而单子结构则完全保留了它。从功能程序员的角度来看,这种差异的实际含义是什么?

我问这个问题是为了更好地理解应用性/单语,以及引起不同表达的原因。

haskell functional-programming monads applicative monoids
1个回答
7
投票

我们应该整理一下,我们在这里处理三个截然不同的半身像:

  • Haskell中的Monoid,即Monoid类的实例。这些是value-level monoids,即您将Haskell值(例如列表)组合在一起。
  • 从数学上讲,应用程序是monoidal functors,但对于等腰线而言,您无法编写Monoid实例;在Haskell上下文中,它是由单元类型()和元组构造函数(,)构造的type-level monoid。 (请注意,如果您假装(Int, (String, Bool))((Int, String), Bool)是相同的类型,则这只是一个monoid。)这些元组在Applicative类的方法中不是直接可见的,但这仅仅是因为它们已被隐藏通过咖喱。该类的更笼统的表述是

    class Functor f => Monoidal f where
      funit ::    ()     -> f  ()
      fzip :: (f a, f b) -> f (a,b)
    

    证明这等效于标准Applicative类是一个很好的练习。 Monoidal函子的特征实际上在于它在执行其函子映射时保留了此(,) monoid结构,但实际上与任何特定的Haskell monoid并没有多大关系。

  • Monad,作为一个半幽默的嗡嗡声不停地飘浮,是monofoids in endofunctors。但是,这是我们正在讨论的另一个monoid,即函子应用程序堆栈的monoid。与Applicative一样,该类的数学公式也有所不同:class Monoidal m => Monad m where pure :: a -> m a join :: m (m a) -> m a

    即这里的类人动物是m应用的一种

    composition

    因此,在将涉及monads / applicatives的对象与某些特定Haskell monoid进行比较时,您会得到不同的行为,这真的不足为奇。在某些情况下,两者的行为相同,但基本上可以归结为使用了一个实例,该实例将更高级的单曲面结构退化为某种东西,当与固定的包含类型一起使用时,该东西同构为非参数Monoid实例。
© www.soinside.com 2019 - 2024. All rights reserved.