我试图理解与以下图片相对应的Product
和Coproduct
:
副产品:
据我了解,Haskell中的Product
类型例如:
data Pair = P Int Double
,Sum
类型为:
data Pair = I Int | D Double
如何理解与Sum
和Product
类型有关的图像?
图像来自http://blog.higher-order.com/blog/2014/03/19/monoid-morphisms-products-coproducts/。
答案 0 :(得分:5)
产品(在Haskell中为Tuple
)是具有两个投影的对象。这些是将产品投影到其各自的因素fst
和snd
的功能。
相反,副产品(在Haskell中为Either
)是具有两个 injections 的对象。这些是将<{>}和lefts
的各个求和数注入的函数。
请注意,产品和副产品都需要满足通用属性。我推荐Bartosz Milewski的introduction和他的lecture。
答案 1 :(得分:4)
据我所知,这些图表背后的想法是给您:
A
,B
和Z
f
和g
(在第一张图中,f :: Z -> A
和g :: Z -> B
,在第二张图中,箭头为“另一种方式”,因此f :: A -> Z
和g :: B -> Z
)。我现在将集中在第一个图表上,这样我就不必在稍有变化的情况下重复两次。
无论如何,鉴于上述情况,我们的想法是存在一个类型M
以及函数fst :: M -> A
,snd :: M -> B
和h :: Z -> M
,就像数学家所说的那样,图表“通勤”。这仅表示在给定图中的任何两个点的情况下,如果您以任何方式遵循箭头的指示,则得到的功能是相同的。也就是说,f
与fst . h
相同,g
与snd . h
很容易看出,无论Z
是什么,对类型(A, B)
以及通常的Haskell函数fst
和snd
都满足这一要求-以及h
的适当选择,即:
h z = (f z, g z)
简单地满足了要转换图的两个必需身份。
这是该图的基本说明。但是您可能会对Z
在所有这方面的角色感到有些困惑。之所以会出现这种情况,是因为实际上所说的要强大得多。就是说,给定A
,B
,f
和g
,存在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)
这些图未传达的一件事是哪些是输入,哪些是输出。我将从产品开始,要特别注意将交给您的东西,以及您必须烹饪的东西。
一个产品说:
我们经常假装有一个Hask类别,其中的对象是具体的(单态)类型,而箭头是适当类型的Haskell函数。让我们看看上面的协议如何发挥作用,并证明Haskell的data Pair a b = P a b
是Hask中的产品。
a
和B = b
。我必须产生一个对象(类型)和两个箭头(函数)。我选择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
z
和两个箭头(函数); f
的类型为z -> a
,g
的类型为z -> b
。我必须产生类型为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
根据需要。
联产品的故事相似,但对以下所述的协议进行了细微调整:
修改上面有关产品和Pair
的讨论以使其适用于副产品和data Copair a b = L a | R b
应该很简单。