Why do We Need Sum Types?

前端 未结 4 629
[愿得一人]
[愿得一人] 2021-02-08 04:56

Imagine a language which doesn\'t allow multiple value constructors for a data type. Instead of writing

data Color = White | Black | Blue

we wo

4条回答
  •  囚心锁ツ
    2021-02-08 05:38

    I will try to expand the categorical argument mentioned by @BenjaminHodgson.

    Haskell can be seen as the category Hask, in which objects are types and morphisms are functions between types (disregarding bottom).

    We can define a product in Hask as tuple - categorically speaking it meets the definition of the product:

    A product of a and b is the type c equipped with projections p and q such that p :: c -> a and q :: c -> b and for any other candidate c' equipped with p' and q' there exists a morphism m :: c' -> c such that we can write p' as p . m and q' as q . m.

    Read up on this in Bartosz' Category Theory for Programmers for further information.

    Now for every category, there exists the opposite category, which has the same morphism but reverses all the arrows. The coproduct is thus:

    The coproduct c of a and b is the type c equipped with injections i :: a -> c and j :: b -> c such that for all other candidates c' with i' and j' there exists a morphism m :: c -> c' such that i' = m . i and j' = m . j.

    Let's see how the tagged and untagged union perform given this definition:

    The untagged union of a and b is the type a :|: b such that:

    • i :: a -> a :|: b is defined as i a = a and
    • j :: b -> a :|: b is defined as j b = b

    However, we know that a :|: a is isomorphic to a. Based on that observation we can define a second candidate for the product a :|: a :|: b which is equipped with the exact same morphisms. Therefore, there is no single best candidate, since the morphism m between a :|: a :|: b and a :|: b is id. id is a bijection, which implies that m is invertible and "convert" types either way. A visual representation of that argument. Replace p with i and q with j.

    Restricting ourselves Either, as you can verify yourself with:

    • i = Left and
    • j = Right

    This shows that the categorical complement of the product type is the disjoint union, not the set-based union.

    The set union is part of the disjoint union, because we can define it as follows:

    data Left a = Left a
    data Right b = Right b
    type DisjUnion a b = Left a :|: Right b
    

    Because we have shown above that the set union is not a valid candidate for the coproduct of two types, we would lose many "free" properties (which follow from parametricity as leftroundabout mentioned) by not choosing the disjoint union in the category Hask (because there would be no coproduct).

提交回复
热议问题