From 33cd4f5f685105746be30bf27d85455b4b9c8651 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Sat, 28 Mar 2020 22:26:47 -0700 Subject: [PATCH] Start working on part 11 of compiler series --- .../11_compiler_polymorphic_data_types.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 content/blog/11_compiler_polymorphic_data_types.md diff --git a/content/blog/11_compiler_polymorphic_data_types.md b/content/blog/11_compiler_polymorphic_data_types.md new file mode 100644 index 0000000..a29d7cb --- /dev/null +++ b/content/blog/11_compiler_polymorphic_data_types.md @@ -0,0 +1,63 @@ +--- +title: Compiling a Functional Language Using C++, Part 11 - Polymorphic Data Types +date: 2020-03-28T20:10:35-07:00 +draft: true +tags: ["C and C++", "Functional Languages", "Compilers"] +--- +[In part 10]({{< relref "10_compiler_polymorphism.md" >}}), we managed to get our +compiler to accept functions that were polymorphically typed. However, a piece +of the puzzle is still missing: while our _functions_ can handle values +of different types, the same cannot be said for our _data types_. This means +that we cannot construct data structures that can contain arbitrary types. +While we can define and use a list of integers, if we want to also have a +list of booleans, we must copy all of our constructors and define a new data type. +Worse, not only do we have to duplicate the constructors, but also all the functions +that operate on the list. As far as our compiler is concerned, a list of +integers and a list of booleans are entirely different beasts, and cannot +be operated on by the same code. + +To make polymorphic data types possible, we must extend our language (and type +system) a little. We will now allow for something like this: + +``` +data List a = { Nil, Cons a List } +``` + +In the above snippet, we are no longer declaring a single type, but a collection +of related types, __parameterized__ by a type `a`. Any type can take the place +of `a` to get a list containing that type of element. +Then, `List Int` is a type, +as is `List Bool` and `List (List Int)`. The constructors in the snippet also +get polymorphic types: + +{{< latex >}} +\text{Nil} : \forall a \; . \; \text{List} \; a \\ +\text{Cons} : \forall a \; . \; a \rightarrow \text{List} \; a \rightarrow \text{List} \; a +{{< /latex >}} + +When you call `Cons`, the type of the resulting list varies with the type of element +you pass in. The empty list `Nil` is a valid list of any type, since, well, it's +empty. + +Let's talk about `List` itself, now. I suggest that we ponder the following table: + +\\(\\text{List}\\)|\\(\\text{Cons}\\) +----|---- +\\(\\text{List}\\) is not a type; it must be followed up with arguments, like \\(\\text{List} \\; \\text{Int}\\).|\\(\\text{Cons}\\) is not a list; it must be followed up with arguments, like \\(\\text{Cons} \\; 3 \\; \\text{Nil}\\). +\\(\\text{List} \\; \\text{Int}\\) is in its simplest form.|\\(\\text{Cons} \\; 3 \\; \\text{Nil}\\) is in its simplest form. +\\(\\text{List} \\; \\text{Int}\\) is a type.|\\(\\text{Cons} \\; 3 \\; \\text{Nil}\\) is a value of type \\(\\text{List} \\; \\text{Int}\\). + +I hope that the similarities are quite striking. I claim that +`List` is quite similar to a constructor `Cons`, except that it occurs +in a different context: whereas `Cons` is a way to create values, +`List` is a way to create types. Indeed, while we call `Cons` a constructor, +it's typicall to call `List` a __type constructor__. +We know that `Cons` is a function which +assigns to values (like `3` and `Nil`) other values (like `Cons 3 Nil`, or `[3]` for +short). In a similar manner, `List` can be thought of as a function +that assigns to types (like `Int`) other types (like `List Int`). We can +even claim that it has a type: + +{{< latex >}} +\text{List} : \text{Type} \rightarrow \text{Type} +{{< /latex >}}