
On Nov 21, 2006, at 8:01 AM, Simon Marlow wrote:
Malcolm Wallace wrote:
Taral
writes: On 11/20/06, Malcolm Wallace
wrote: newtype Wrapper a = Wrap a convert :: [a] -> [Wrapper a] convert xs = map Wrap xs
Interesting! Looks like the compiler lacks rules for optimizing "map id" &c.\ And not all compilers have optimisation phases. Your coercion does assume that the underlying runtime doesn't have some kind of type-tag implementation of type classes. I believe this is guaranteed by the definition of newtype in the Language Report.
The language doesn't say anything about the runtime representation of newtype. It so happens that the semantics lead to the obvious implementation of a newtype as a type cast (that was the reason for introducing newtype, after all), but there's nothing to say you have to implement it this way. It would be wrong to require that unsafeCoerce let you convert between a newtype and its underlying type across implementations.
From Section 4.2.3, from the Haskell report: A declaration of the form newtype cx => T u1 ... uk = N t introduces a new type whose representation is the same as an existing type. The type (T u1 ... uk) renames the datatype t. It differs from a type synonym in that it creates a distinct type that must be explicitly coerced to or from the original type. Also, unlike type synonyms, newtype may be used to define recursive types. The constructor N in an expression coerces a value from type t to type (T u1 ... uk). Using N in a pattern coerces a value from type (T u1 ... uk) to type t. These coercions may be implemented without execution time overhead; newtype does not change the underlying representation of an object. I'd say that discusses the runtime representation.
Cheers, Simon
Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG