<div dir="ltr">Hrm. It's a shame that supporting this map/coerce RULE causes such pain.<div><br></div><div>This makes me wonder: can we get rid of this RULE? Eric Mertens pointed out a trick [1] that's used in the profunctors library to make mapping coerce over certain Profunctors more efficient. To adapt this trick for Functor, we'd need to add another class method:</div><div><br></div><div>    class Functor f where</div><div>        fmap :: (a -> b) -> f a -> f b</div><div>        (<#>) :: Coercible a b => (a -> b) -> f a -> f b</div><div>        (<#>) = \f -> \p -> p `seq` fmap f p</div><div><br></div><div>Now, when implementing Functor instances, if we are working with a datatype whose role is representational or phantom, we can make (<#>) really fast:</div><div><br></div><div>    data List a = Nil | Cons a (List a)</div><div>    instance Functor List where</div><div>        fmap = ...</div><div>        (<#>) = coerce</div><div><br></div><div>Now, instead of relying on (map MkNewtype Nil) to rewrite to Nil, we can just use (MkNewtype <#> Nil)! No map/coerce RULE necessary :)</div><div><br></div><div>OK, I realize that suggesting that we remove the RULE is perhaps a touch too far. But it does sting that we have to pay hefty compilation penalties because of its existence...</div><div><br></div><div>Ryan S.</div><div>-----</div><div>[1] <a href="http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor-Unsafe.html#v:-35-">http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor-Unsafe.html#v:-35-</a>.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 31, 2017 at 7:25 PM, Richard Eisenberg <span dir="ltr"><<a href="mailto:rae@cs.brynmawr.edu" target="_blank">rae@cs.brynmawr.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
> On May 31, 2017, at 5:21 PM, Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com">ryan.gl.scott@gmail.com</a>> wrote:<br>
> Does you know what might be going on here?<br>
<br>
</span>I think so, but I don't know how to fix it.<br>
<br>
The commit you found (thank you!) makes simple_opt_expr (the "simple optimizer", run directly after desugaring, even with -O0) a little more selective in what `case` expressions it throws away. Previous to that commit, the optimizer would throw away a `case error "deferred type error" of _ -> ...` which is terrible. It seems that you have discovered that we are now too timid in throwing away unhelpful cases. It would be interesting to know what the newly-retained cases look like, so that we might throw them away.<br>
<br>
But there remains a mystery: Why do we need this code at all? Reading Note [Getting the map/coerce RULE to work] closely, it seems we need to simplify<br>
<br>
  forall a b (co :: a ~R# b).<br>
    let dict = MkCoercible @* @a @b co in<br>
    case Coercible_SCSel @* @a @b dict of<br>
      _ [Dead] -> map @a @b (\(x :: a) -> case dict of<br>
         MkCoercible (co :: a ~R# b) -> x |> co) = let dict = ... in ...<br>
<br>
to<br>
<br>
  forall a b (co :: a ~R# b).<br>
    map @a @b (\(x :: a) -> x |> co) = \(x :: [a]) -> x |> [co]<br>
<br>
Part of doing so is to drop the `case Coercible_SCSel ...`, which gets in the way. The mystery is why this needs special code -- shouldn't the eliminate-case-of-known-<wbr>constructor do the trick? This would require unfolding Coercible_SCSel. Does that happen? It would seem not... but maybe it should, which would remove the special-case code that I changed in that commit, and quite likely would simplify much more code besides.<br>
<br>
So: Is Coercible_SCSel unfolded during simple_opt? If not, what wonderful or terrible things happen if we do? If so, why does case-of-known-constructor not work here? My guess is that answering these questions may solve the original problem, but this guess could be wrong.<br>
<span class="HOEnZb"><font color="#888888"><br>
Richard<br>
<br>
</font></span></blockquote></div><br></div>