了解产品和副产品图

时间:2019-05-07 10:05:33

标签: scala haskell tuples category-theory either

我试图理解与以下图片相对应的ProductCoproduct

产品: enter image description here

副产品:

enter image description here

据我了解,Haskell中的Product类型例如:

data Pair = P Int Double

Sum类型为:

data Pair = I Int | D Double 

如何理解与SumProduct类型有关的图像?

图像来自http://blog.higher-order.com/blog/2014/03/19/monoid-morphisms-products-coproducts/

3 个答案:

答案 0 :(得分:5)

产品(在Haskell中为Tuple)是具有两个投影的对象。这些是将产品投影到其各自的因素fstsnd的功能。

相反,副产品(在Haskell中为Either)是具有两个 injections 的对象。这些是将<{>}和lefts的各个求和数注入的函数。

请注意,产品和副产品都需要满足通用属性。我推荐Bartosz Milewski的introduction和他的lecture

答案 1 :(得分:4)

据我所知,这些图表背后的想法是给您:

  • 类型ABZ
  • 所指示类型的功能fg(在第一张图中,f :: Z -> Ag :: Z -> B,在第二张图中,箭头为“另一种方式”,因此f :: A -> Zg :: B -> Z)。

我现在将集中在第一个图表上,这样我就不必在稍有变化的情况下重复两次。

无论如何,鉴于上述情况,我们的想法是存在一个类型M以及函数fst :: M -> Asnd :: M -> Bh :: Z -> M,就像数学家所说的那样,图表“通勤”。这仅表示在给定图中的任何两个点的情况下,如果您以任何方式遵循箭头的指示,则得到的功能是相同的。也就是说,ffst . h相同,gsnd . h

相同

很容易看出,无论Z是什么,对类型(A, B)以及通常的Haskell函数fstsnd都满足这一要求-以及h的适当选择,即:

h z = (f z, g z)

简单地满足了要转换图的两个必需身份。

这是该图的基本说明。但是您可能会对Z在所有这方面的角色感到有些困惑。之所以会出现这种情况,是因为实际上所说的要强大得多。就是说,给定ABfg,存在M以及函数fst和{{1} },您可以为 any 类型的snd构造这样的图(这也意味着要提供功能Z)。而且,只有一个函数h :: Z -> M可以满足所需的属性。

很明显,一旦您使用它并理解了各种要求,对h和其他各种同构类型(基本上意味着(A, B)是您定义{{ 1}})是唯一满足此要求的事物。还有其他类型的MyPair A B也可以使用,但是会给出各种不同的data MyPair a b = MyPair a b-例如。将M设为三元组h,并提取M(A, B, Int)(在数学术语中为“投影到”)第一和第二成分,然后提取{{1} }就是您要命名的任何fst的功能。

自从我学习数学(尤其是类别理论)以来,已经太久了,无法证明snd对是满足我们所讨论的“通用属性”的唯一类型-但是要休息一下可以肯定的是,您真的不需要了解(或实际上没有任何一项)就可以在Haskell中使用乘积和求和类型进行编程。

第二张图大致相同,但所有箭头都相反。在这种情况下,h z = (f z, g z, x)x :: Int的“副产品”或“和” (A, B)变成M(或等价的东西),而{{1} }将定义为:

A

答案 2 :(得分:3)

这些图未传达的一件事是哪些是输入,哪些是输出。我将从产品开始,要特别注意将交给您的东西,以及您必须烹饪的东西。

一个产品说:

  1. 您给我两个对象A和B。
  2. 我给你一个新的对象M,两个箭头fst:M-> A和snd:M-> B。
  3. 您给我一个对象Z和两个箭头f:Z-> A和g:Z-> B。
  4. 我给您一个箭头h:Z-> M,使该图变通(...并且该箭头由到目前为止所做的选择唯一确定)。

我们经常假装有一个Hask类别,其中的对象是具体的(单态)类型,而箭头是适当类型的Haskell函数。让我们看看上面的协议如何发挥作用,并证明Haskell的data Pair a b = P a b是Hask中的产品。

  1. 您给我两个对象(类型),A = {a和B = b
  2. 我必须产生一个对象(类型)和两个箭头(函数)。我选择M = {Pair a b。然后,我必须编写类型为Pair a b -> a(对于箭头fst:M-> A)和Pair a b -> b(对于箭头snd:M-> B)的函数。我选择:

    fst :: Pair a b -> a
    fst (P a b) = a
    
    snd :: Pair a b -> b
    snd (P a b) = b
    
  3. 您给我一个对象(类型)Z = {z和两个箭头(函数); f的类型为z -> ag的类型为z -> b
  4. 我必须产生类型为h的函数z -> Pair a b。我选择:

    h = \z -> P (f z) (g z)
    

    h是使图上下班所必需的。这意味着从图中开始并在同一对象处结束的任何两条路径应相等。对于给定的图,这意味着我们必须证明它满足两个方程式:

    f = fst . h
    g = snd . h
    

    我将证明第一个;第二个相似。

    fst . h
    = { definition of h }
    fst . (\z -> P (f z) (g z))
    = { definition of (.) }
    \v -> fst ((\z -> P (f z) (g z)) v)
    = { beta reduction }
    \v -> fst (P (f v) (g v))
    = { definition of fst }
    \v -> f v
    = { eta reduction }
    f
    

    根据需要。

联产品的故事相似,但对以下所述的协议进行了细微调整:

  1. 您给我两个对象A和B。
  2. 我给您一个新的对象W,向左两个箭头:A-> W,向右:B-> W。
  3. 您给我一个对象Z和箭头f:A-> Z和g:A-> Z。
  4. 我给您一个箭头h:W-> Z,使图表上下班(...并且该箭头由到目前为止的选择唯一确定)。

修改上面有关产品和Pair的讨论以使其适用于副产品和data Copair a b = L a | R b应该很简单。