Skip to content

Commit

Permalink
Prepare article for publication
Browse files Browse the repository at this point in the history
  • Loading branch information
ploeh committed Sep 16, 2024
1 parent 23a140b commit 9127753
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ <h3 id="a90284d241c4463583401504395a4a8a">
<li><a href="/2022/07/11/functor-relationships">Functor relationships</a>
<ul>
<li><a href="/2022/07/18/natural-transformations">Natural transformations</a></li>
<li>Functor products</li>
<li><a href="/2024/09/16/functor-products">Functor products</a></li>
<li>Functor sums</li>
<li>Functor compositions</li>
<li>Traversals</li>
Expand Down
2 changes: 1 addition & 1 deletion _posts/2018-03-19-functors-applicatives-and-friends.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
<li><a href="/2022/07/11/functor-relationships">Functor relationships</a>
<ul>
<li><a href="/2022/07/18/natural-transformations">Natural transformations</a></li>
<li>Functor products</li>
<li><a href="/2024/09/16/functor-products">Functor products</a></li>
<li>Functor sums</li>
<li>Functor compositions</li>
<li>Traversals</li>
Expand Down
2 changes: 1 addition & 1 deletion _posts/2022-07-11-functor-relationships.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h3 id="70383da35af346f6b2dc3095a1bf7273">
</p>
<ul>
<li><a href="/2022/07/18/natural-transformations">Natural transformations</a></li>
<li>Functor products</li>
<li><a href="/2024/09/16/functor-products">Functor products</a></li>
<li>Functor sums</li>
<li>Functor compositions</li>
<li>Traversals</li>
Expand Down
2 changes: 1 addition & 1 deletion _posts/2022-07-18-natural-transformations.html
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,6 @@ <h3 id="103675f9845b4aa1b32f59a510280a53">
A few natural transformations may be true isomorphisms, but in general, being able to go in both directions isn't required. In degenerate cases, a natural transformation may throw away all information and map to a general empty value like the empty List or an empty Maybe value.
</p>
<p>
<strong>Next:</strong> Functor products.
<strong>Next:</strong> <a href="/2024/09/16/functor-products">Functor products</a>.
</p>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
layout: post
title: "Functor products"
description: "A tuple or class of functors is also a functor."
date: 2022-08-16 7:45 UTC
description: "A tuple or class of functors is also a functor. An article for object-oriented developers."
date: 2024-09-16 6:08 UTC
tags: [Software Design, Functional Programming]
---
{% include JB/setup %}
Expand All @@ -21,7 +21,7 @@
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 like <code>Foo&lt;T&gt;</code> (C# syntax) or <code>Bar&lt;T1, T2&gt;</code>, being able to recognize it as a functor can come in handy. One scenario is if you yourself have just defined such a data type. Recognizing that it's a functor strongly suggests that you should give it a <code>Select</code> method in C#, a <code>map</code> function in <a href="https://fsharp.org/">F#</a>, and so on.
</p>
<p>
Not all generic types give rise to a (covariant) functor. Some are rather <a href="/2021/09/02/contravariant-functors">contravariant functors</a>, some are <a href="/2022/08/01/invariant-functors">invariant</a>, and some again are <a href="/2020/10/19/monomorphic-functors">monomorphic</a>.
Not all generic types give rise to a (covariant) functor. Some are rather <a href="/2021/09/02/contravariant-functors">contravariant functors</a>, and some are <a href="/2022/08/01/invariant-functors">invariant</a>.
</p>
<p>
If, on the other hand, you have a data type which is a product of two or more (covariant) functors <em>with the same type parameter</em>, then the data type itself gives rise to a functor. You'll see some examples in this article.
Expand Down Expand Up @@ -93,7 +93,7 @@ <h3 id="e3b18df7ac4440d7aada000ce27044f3">
<pre><span style="color:blue;">type</span>&nbsp;ListZipper&nbsp;a&nbsp;=&nbsp;([a],[a])</pre>
</p>
<p>
In the article <a href="">A List Zipper in C#</a> you saw how the <code><span style="color:#2b91af;">ListZipper</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> class composes two <code><span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects.
In the article <a href="/2024/08/26/a-list-zipper-in-c">A List Zipper in C#</a> you saw how the <code><span style="color:#2b91af;">ListZipper</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> class composes two <code><span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects.
</p>
<p>
<pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;values;
Expand Down Expand Up @@ -196,7 +196,7 @@ <h3 id="25e4dea36f644217ba1e28f2a509f3ab">
Binary tree Zipper <a href="#25e4dea36f644217ba1e28f2a509f3ab">#</a>
</h3>
<p>
In <a href="">A Binary Tree Zipper in C#</a> you saw that the <code><span style="color:#2b91af;">BinaryTreeZipper</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> class has two class fields:
In <a href="/2024/09/09/a-binary-tree-zipper-in-c">A Binary Tree Zipper in C#</a> you saw that the <code><span style="color:#2b91af;">BinaryTreeZipper</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> class has two class fields:
</p>
<p>
<pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">BinaryTree</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;Tree&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;}
Expand Down Expand Up @@ -229,7 +229,7 @@ <h3 id="1179fc33850d430780c843583c16adcb">
By induction you can generalize this result to any arity. The point is that the only data type you need to describe a product is a pair.
</p>
<p>
Haskell's <a href="https://hackage.haskell.org/package/base">base</a> library defines a specialized container called <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Product.html">Product</a> for this very purpose. If you have two <code>Functor</code> instances, you can <code>Pair</code> them up, and they become a single <code>Functor</code>.
Haskell's <a href="https://hackage.haskell.org/package/base">base</a> library defines a specialized container called <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Product.html">Product</a> for this very purpose: If you have two <code>Functor</code> instances, you can <code>Pair</code> them up, and they become a single <code>Functor</code>.
</p>
<p>
Let's start with a <code>Pair</code> of <code>Maybe</code> and a list:
Expand All @@ -256,7 +256,7 @@ <h3 id="1179fc33850d430780c843583c16adcb">
Pair (Identity False) (Pair (Just False) [True,True,False])</pre>
</p>
<p>
This example now introduces the <code>Identity</code> container as a third <code>Functor</code> instance. I could have used any other <code>Functor</code> instance instead of <code>Identity</code>, but some of them are more awkward to create or display. For example, the <a href="/2021/08/30/the-reader-functor">Reader</a> or <a href="/2021/07/19/the-state-functor">State</a> functors have no <code>Show</code> instances in Haskell, meaning GHCi doesn't know how to print them as values. Other <code>Functor</code> instances didn't work as well for the example, since they tend to be more awkward to create. As an example, any non-trivial <a href="https://hackage.haskell.org/package/containers/docs/Data-Tree.html#t:Tree">Tree</a> requires substantial editor space to express.
This example now introduces the <code>Identity</code> container as a third <code>Functor</code> instance. I could have used any other <code>Functor</code> instance instead of <code>Identity</code>, but some of them are more awkward to create or display. For example, the <a href="/2021/08/30/the-reader-functor">Reader</a> or <a href="/2021/07/19/the-state-functor">State</a> functors have no <code>Show</code> instances in Haskell, meaning that GHCi doesn't know how to print them as values. Other <code>Functor</code> instances didn't work as well for the example, since they tend to be more awkward to create. As an example, any non-trivial <a href="https://hackage.haskell.org/package/containers/docs/Data-Tree.html#t:Tree">Tree</a> requires substantial editor space to express.
</p>
<h3 id="329c3274f8f54171905d747867fc293b">
Conclusion <a href="#329c3274f8f54171905d747867fc293b">#</a>
Expand Down

0 comments on commit 9127753

Please sign in to comment.