Newtype wrappers
wren ng thornton
wren at freegeek.org
Mon Jan 21 05:33:12 CET 2013
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
More information about the Glasgow-haskell-users
mailing list