title: Why doesn't `coerce` implicitly apply Compose to these functions?
body: <p>Consider this type:</p>
  <pre><code>data Vec3 = Vec3 {_x, _y, _z :: Int}
  </code></pre>
  <p>I have some functions that all take the same input, and may fail to compute a field:</p>
  <pre><code>data Input
  getX, getY, getZ :: Input -&gt; Maybe Int
  </code></pre>
  <p>I can write a function that tries all three of these field constructors:</p>
  <pre><code>v3 :: Input -&gt; Maybe Vec3
  v3 i = liftA3 Vec3 (getX i) (getY i) (getZ y)
  </code></pre>
  <p>But it's kinda annoying to have to pass that <code>i</code> input around three times. Functions are themselves an applicative functor, and so one can replace <code>foo x = bar (f x) (g x) (h x)</code> with <code>foo = liftA3 bar f g h</code>.</p>
  <p>Here, my <code>bar</code> is <code>liftA3 Vec3</code>, so I could write</p>
  <pre><code>v3' :: Input -&gt; Maybe Vec3
  v3' = liftA3 (liftA3 Vec3) getX getY getZ
  </code></pre>
  <p>But this is a bit gross, and when we work with composed applicatives in this way (<code>((-&gt;) Input)</code> and <code>Maybe</code>), there's the <code>Compose</code> newtype to handle this kind of thing. With it, I can write</p>
  <pre><code>v3'' :: Input -&gt; Maybe Vec3
  v3'' = getCompose go
    where go = liftA3 Vec3 x y z
          x = Compose getX
          y = Compose getY
          z = Compose getZ
  </code></pre>
  <p>Okay, not exactly a great character savings, but we're now working with one combined functor instead of two, which is nice. And I thought I could use <code>coerce</code> to win me back some of the characters: after all, <code>x</code> is just a newtype wrapper around <code>getX</code>, and likewise for the other fields. So I thought I could coerce <code>liftA3</code> into accepting three <code>Input -&gt; Maybe Vec3</code> instead of accepting three <code>Compose ((-&gt;) Input) Maybe Vec3</code>:</p>
  <pre><code>v3''' :: Input -&gt; Maybe Vec3
  v3''' = getCompose go
    where go = coerce liftA3 Vec3 getX getY getZ
  </code></pre>
  <p>But this <em>doesn't</em> work, yielding the error message:</p>
  <pre><code>tmp.hs:23:14: error:
      • Couldn't match representation of type ‘f0 c0’
                                 with that of ‘Input -&gt; Maybe Int’
          arising from a use of ‘coerce’
      • In the expression: coerce liftA3 Vec3 getX getY getZ
        In an equation for ‘go’: go = coerce liftA3 Vec3 getX getY getZ
        In an equation for ‘v3'''’:
            v3'''
              = getCompose go
              where
                  go = coerce liftA3 Vec3 getX getY getZ
     |
  23 |   where go = coerce liftA3 Vec3 getX getY getZ
     |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  </code></pre>
  <p>I don't understand why not. I can write <code>coerce getX :: Compose ((-&gt;) Input) Maybe Int</code>, and this is fine. And generally a function can be coerced in order to make it coerce its arguments or return type, as in</p>
  <pre><code>coerce ((+) :: Int -&gt; Int -&gt; Int) (Max (5::Int)) (Min (8::Int)) :: Sum Int
  </code></pre>
  <p>And I can in fact write out all the <code>coerce</code>s individually:</p>
  <pre><code>v3'''' :: Input -&gt; Maybe Vec3
  v3'''' = getCompose go
    where go = liftA3 Vec3 x y z
          x = coerce getX
          y = coerce getY
          z = coerce getZ
  </code></pre>
  <p>So why can't <code>liftA3</code> itself be coerced to accept <code>getX</code> instead of <code>coerce getX</code>, allowing me to use <code>v3'''</code>?</p>