On 1/14/13 2:47 PM, Stephen Paul Weber wrote:
Somebody claiming to be Simon Peyton-Jones wrote:
 *   For x1 we can write map MkAge x1 :: [Age]. But this does not
follow  the newtype cost model: there will be runtime overhead from
executing the  map at runtime, and sharing will be lost too. Could GHC
optimise the map  somehow?

My friend pointed out something interesting:

If GHC can know that MkAge is just id (in terms of code, not in terms of
type), which seems possible, and if the only interesting case is a
Functor, which seems possible, then a RULE fmap id = id would solve
this.  No?

The problem is precisely that the types don't line up, so that rule won't fire. A more accurate mental model is that when we write:

    newtype Foo = MkFoo { unFoo :: Bar }

the compiler generates the definitions:

    MkFoo :: Bar -> Foo
    MkFoo = unsafeCoerce

    unFoo :: Foo -> Bar
    unFoo = unsafeCoerce

(among others). So the rule we want is:

    fmap unsafeCoerce = unsafeCoerce

Except, there are functions other than fmap which behave specially on identity functions. Another major one is (.) where newtypes (but not id) introduce an eta-expansion that can ruin performance.

It strikes me that the cleanest solution would be to have GHC explicitly distinguish (internally) between "identity" functions and other functions, so that it can ensure that it treats all "identity" functions equally. Where that equality means rewrite rules using id, special optimizations about removing id, etc, all carry over to match on other "identity" functions as well.

--
Live well,
~wren

_______________________________________________
Glasgow-haskell-users mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to