{"id":711,"date":"2016-01-01T21:00:06","date_gmt":"2016-01-01T21:00:06","guid":{"rendered":"http:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/?p=711"},"modified":"2017-03-04T06:22:43","modified_gmt":"2017-03-04T06:22:43","slug":"insights-into-why-a-contravariant-type-cant-be-a-haskell-functor","status":"publish","type":"post","link":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/?p=711","title":{"rendered":"Insights into why a contravariant type can\u2019t be a Haskell Functor"},"content":{"rendered":"<p>In learning Haskell&#8217;s core types, type classes, and concepts, one often finds counterexamples useful in learning what these abstract concepts &#8220;really are&#8221;. Perhaps one of the most well-understood type class hierarchies is <code>Functor-Applicative-Monad<\/code>. We encounter <code>Functor<\/code> in the context of things that are &#8220;mappable&#8221;. It&#8217;s a producer, and using <code>fmap<\/code> we can &#8220;post-transform&#8221; all of the things that it produces in a way that preserves any underlying structure.<\/p>\n<p>We quickly become familiar with a number of useful functors, like <code>Maybe<\/code>, <code>[]<\/code>, <code>(-&gt;) r<\/code>, <code>IO<\/code>. Functors seem to be everywhere. So, then, one asks, what might be a parameterized type that&#8217;s <em>not<\/em> a functor? The go-to example is something that&#8217;s contravariant in its type parameter, like <code>a -&gt; Int<\/code>, as a type-level function of parameter <code>a<\/code>. There doesn&#8217;t seem to be any <em>useful<\/em> way to make it a <code>Functor<\/code> in <code>a<\/code>. That said, seemingly &#8220;useless&#8221; type-level artifacts are often quite useful, like the <code>Const Functor<\/code>, defined as <code>Const r a ~= r<\/code> (the <code>a<\/code> is a phantom type and functions being <code>fmap<\/code>ed are ignored). So usefulness in this world isn&#8217;t always intuitive. Still, it remains true that something like <code>a -&gt; Int<\/code> is <em>not<\/em> a functor? Why?<\/p>\n<p>Let&#8217;s work with the type <code>a -&gt; Bool<\/code>, just because it&#8217;s the simplest example of what goes wrong. Is there a way to make a <code>Functor<\/code> instance for that? To me, it&#8217;s not intuitive that that thing isn&#8217;t a <code>Functor<\/code>. It&#8217;s &#8220;almost&#8221; a set (stepping around, for a moment, debates about what is a set) and <code>Set<\/code>, meaning the actual collection type in <code>Data.Set<\/code> is &#8220;almost&#8221; a <code>Functor<\/code>. It&#8217;s not one, because a <code>Functor<\/code> demands that the mapping be structure-preserving, which a set&#8217;s notion of mapping is not (for example, if you map the squaring function on the set {2, -2}, you get a smaller set, {4}). There are many ways to get at the point that <code>Set<\/code> is not a <code>Functor<\/code>, most relying on the fact that <code>Set a<\/code>&#8216;s methods almost invariably require <code>Eq a<\/code> and <code>Ord a<\/code>. But what about the type-agnostic &#8220;<code>(&lt;-) a<\/code>&#8221; (my notation) above? It places no such constraints on <code>a<\/code>.<\/p>\n<p>To answer this, let&#8217;s try to create the method, <code>fmap<\/code>, on which <code>Functor<\/code> relies.<\/p>\n<blockquote>\n<p><code><br \/>\n-- pretend Haskell supports (&lt;-) b a as a syntax for (-&gt;) a b = a -&gt; b<\/code><\/p>\n<p><code>instance Functor (&lt;-) Bool where<\/code><\/p>\n<p><code>-- fmap :: (a -&gt; b) -&gt; f a -&gt; f b<\/code><br \/>\n<code>-- in this case, (a -&gt; b) -&gt; (a -&gt; Bool) -&gt; (b -&gt; Bool)<\/code><br \/>\n<code>fmap f x = ??<\/code><\/p>\n<\/blockquote>\n<p>The type signature that we&#8217;re demanding of our <code>fmap<\/code> is an interesting one: <code>(a -&gt; b) -&gt; (a -&gt; Bool) -&gt; (b -&gt; Bool)<\/code>. Notice that such a function doesn&#8217;t have any <code>a<\/code> to work with. One might not exist: the <code>Functor<\/code> needs to be valid over empty types (e.g. <code>Void<\/code>; note that <code>[Void]<\/code> is not empty but has exactly one element, <code>[]<\/code>). In typical <code>Functor<\/code> cases, the <code>a = Void<\/code> case is handled soundly. For example, consider the list case: (<code>[] :: [Void]<\/code> maps to <code>[] :: [b]<\/code> for any <code>b<\/code>), and any non-empty list has <code>a<\/code>s to work with. In this case, <code>fmap<\/code>&#8216;s type signature gives us two things that we can do with <code>a<\/code>&#8216;s but no <code>a<\/code>. This means that we have to ignore the first two arguments; we can&#8217;t use them.<\/p>\n<p><code>instance Functor (&lt;-) Bool where<\/code><\/p>\n<p><code>-- fmap :: (a -&gt; b) -&gt; f a -&gt; f b<\/code><br \/>\n<code>-- in this case, (a -&gt; b) -&gt; (a -&gt; Bool) -&gt; (b -&gt; Bool)<\/code><br \/>\n<code>fmap _ _ = (?? :: b -&gt; Bool)<\/code><\/p>\n<p>This rules out any <em>useful<\/em> <code>Functor<\/code>s. In fact, our need for an expression that inhabits <code>b -&gt; Bool<\/code> for any <code>b<\/code> limits us to two non-pathological possibilities: the constant functions! Since we don&#8217;t have any <code>b<\/code> to work with, either, we have to commit to one of those.\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Without_loss_of_generality\">Without loss of generality<\/a>, I&#8217;m going to use the definition <code>fmap _ _ = const True<\/code>. With a few tweaks to what I&#8217;ve done, Haskell will actually allow such a &#8220;<code>Functor<\/code>&#8221; instance to be created. But will it be <em>right<\/em>? It turns out that it won&#8217;t be. To show this, we consult the laws for the <code>Functor<\/code> type class. In fact, we only need the simplest one (Identity): <code>fmap id === id\u00a0<\/code>to refute this one. That law is violated by the constant &#8220;<code>Functor<\/code>&#8221; above:<\/p>\n<p><code>fmap id (const True) = const True -- OK!<\/code><br \/>\n<code>fmap id (const False) = const True -- whoops!<\/code><\/p>\n<p>So it turns out that <code>(&lt;-) Bool<\/code> (my notation) has <em>no<\/em> <code>Functor<\/code> instances at all (the only properly polymorphic candidate fails the type class&#8217;s most basic law) and the more complicated cases fail similarly.<\/p>\n<p>  <a href=\"http:\/\/feeds.wordpress.com\/1.0\/gocomments\/michaelochurch.wordpress.com\/4123\/\" rel=\"nofollow\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/feeds.wordpress.com\/1.0\/comments\/michaelochurch.wordpress.com\/4123\/\" \/><\/a> <img loading=\"lazy\" decoding=\"async\" alt=\"\" border=\"0\" height=\"1\" src=\"https:\/\/pixel.wp.com\/b.gif?host=michaelochurch.wordpress.com&#038;blog=12019234&#038;post=4123&#038;subd=michaelochurch&#038;ref=&#038;feed=1\" width=\"1\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In learning Haskell&#8217;s core types, type classes, and concepts, one often finds counterexamples useful in learning what these abstract concepts &#8220;really are&#8221;. Perhaps one of the most well-understood type class hierarchies is Functor-Applicative-Monad. We encounter Functor in the context of things that are &#8220;mappable&#8221;. It&#8217;s a producer, and using fmap we can &#8220;post-transform&#8221; all of [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18],"tags":[],"class_list":["post-711","post","type-post","status-publish","format-standard","hentry","category-jan-2016"],"_links":{"self":[{"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/posts\/711","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=711"}],"version-history":[{"count":1,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/posts\/711\/revisions"}],"predecessor-version":[{"id":712,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=\/wp\/v2\/posts\/711\/revisions\/712"}],"wp:attachment":[{"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sasamat.xen.prgmr.com\/michaelochurch\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}