diff --git a/_posts/2017-10-4-from-design-patterns-to-category-theory.html b/_posts/2017-10-4-from-design-patterns-to-category-theory.html index 6692daec..572841b0 100644 --- a/_posts/2017-10-4-from-design-patterns-to-category-theory.html +++ b/_posts/2017-10-4-from-design-patterns-to-category-theory.html @@ -254,7 +254,7 @@
diff --git a/_posts/2024-10-14-functor-sums.html b/_posts/2024-10-14-functor-sums.html index e1167f97..c6a330b3 100644 --- a/_posts/2024-10-14-functor-sums.html +++ b/_posts/2024-10-14-functor-sums.html @@ -250,7 +250,7 @@
selector(v)
directly on the 'naked' values, and pass selector
to any other functors' Select
method.
- That's almost all the building blocks we have to declare BinaryTreeZipper<T>
a functor as well, but we need one last theorem before we can do that. We'll conclude this work in the next article.
+ That's almost all the building blocks we have to declare BinaryTreeZipper<T>
a functor as well, but we need one last theorem before we can do that. We'll conclude this work in the next article.
- Next: Functor compositions. + Next: Functor compositions.
diff --git a/_posts/2024-08-20-functor-compositions.html b/_posts/2024-10-28-functor-compositions.html similarity index 91% rename from _posts/2024-08-20-functor-compositions.html rename to _posts/2024-10-28-functor-compositions.html index 61ee9dd5..7872aae3 100644 --- a/_posts/2024-08-20-functor-compositions.html +++ b/_posts/2024-10-28-functor-compositions.html @@ -2,7 +2,7 @@ layout: post title: "Functor compositions" description: "A functor nested within another functor forms a functor. With examples in C# and another language." -date: 2024-08-20 10:58 UTC +date: 2024-10-28 6:58 UTC tags: [Software Design, Functional Programming] --- {% include JB/setup %} @@ -21,10 +21,10 @@ Since functors tend to be quite common, and since they're useful enough that many programming languages have special support or syntax for them, the ability to recognize a potential functor can be useful. Given a type likeFoo<T>
(C# syntax) or Bar<T1, T2>
, being able to recognize it as a functor can come in handy. One scenario is if you yourself have just defined this data type. Recognizing that it's a functor strongly suggests that you should give it a Select
method in C#, a map
function in F#, and so on.
- Not all generic types give rise to a (covariant) functor. Some are rather contravariant functors, some are invariant, and some again are monomorphic. + Not all generic types give rise to a (covariant) functor. Some are rather contravariant functors, and some are invariant.
- If, on the other hand, you have a data type where one functor is nested within another functor while sharing a type parameter, then the data type itself gives rise to a functor. You'll see some examples in this article. + If, on the other hand, you have a data type where one functor is nested within another functor, then the data type itself gives rise to a functor. You'll see some examples in this article.
- Just like PriorityCollection<T>
there's a 'naked' T
value and a collection. The main difference is that here, the collection is of the same type as the object itself: Tree<T>
.
+ Just like PriorityCollection<T>
there's a collection, as well as a 'naked' T
value. The main difference is that here, the collection is of the same type as the object itself: Tree<T>
.
- You've seen a similar example in the previous article, which also had a recursive data structure. If you assume, however, that Tree<T>
gives rise to a functor, then so does the nested composition of putting it in a collection. This means, from the 'theorem' put forth in this article, that IReadOnlyCollection<Tree<T>>
composes as a functor. Finally you have a product of a T
(which is isomorphic to the Identity functor) and that composed functor. From Functor products it follows that that's a functor too, which explains why Tree<T>
forms a functor. The article shows the Select
implementation.
+ You've seen a similar example in the previous article, which also had a recursive data structure. If you assume, however, that Tree<T>
gives rise to a functor, then so does the nested composition of putting it in a collection. This means, from the 'theorem' put forth in this article, that IReadOnlyCollection<Tree<T>>
composes as a functor. Finally you have a product of a T
(which is isomorphic to the Identity functor) and that composed functor. From Functor products it follows that that's a functor too, which explains why Tree<T>
forms a functor. The article shows the Select
implementation.
- In both previous articles you've seen pieces of the puzzle explaining why the binary tree Zipper gives rise to functor. There's one missing piece, however, that we can now finally address. + In both previous articles you've seen pieces of the puzzle explaining why the binary tree Zipper gives rise to functor. There's one missing piece, however, that we can now finally address.
Recall that BinaryTreeZipper<T>
composes these two objects:
@@ -196,7 +196,7 @@
seq<Gen<'a>>
.
- These are all examples of functors within functors. It's not a given that you must treat such combinations as a functor in its own right. To be honest, typically, you don't. On the other hand, if you find yourself writing Select
within Select
, or map
within map
, depending on your language, it might make your code more succinct and readable if you give that combination a specialized functor affordance.
+ These are all examples of functors within functors. It's not a given that you must treat such a combination as a functor in its own right. To be honest, typically, you don't. On the other hand, if you find yourself writing Select
within Select
, or map
within map
, depending on your language, it might make your code more succinct and readable if you give that combination a specialized functor affordance.
Compose
container almost does. Thus, knowing when you can safely give your generic types a Select
method or map
function may come in handy.
- To be honest, though, this result is hardly the most important 'theorem' concerning stacks of functors. In reality, you often run into situation where you do have a stack of functors, but they're in the wrong order. You may have a collection of asynchronous tasks, but you really need an asynchronous task that contains a collection of values. The next article addresses that problem. + To be honest, though, this result is hardly the most important 'theorem' concerning stacks of functors. In reality, you often run into situations where you do have a stack of functors, but they're in the wrong order. You may have a collection of asynchronous tasks, but you really need an asynchronous task that contains a collection of values. The next article addresses that problem.
Next: Traversals.