Mon, 17 Apr 2000 10:07:51 -0400, Chris Okasaki <[EMAIL PROTECTED]> pisze:

> Many of you have run across the problem with newtypes that, although
> it is very cheap to coerce between the newtype and the base type, it
> can be very expensive to coerce between, say, a list of the newtype
> and a list of the base type. Stephanie Weirich and I are working
> on a proposal for the Haskell Workshop addressing this problem,
> and we would welcome any feedback from the community.

Fo me it looks like it requires introducing more special rules to
the language than it's worth it. I don't think that the problem of
converting complex structures of newtypes is so common to justify
introducing not so pretty rules to the language.

GHC has the RULES pragma and unsafeCoerce#, which can be used in a
particular case when the performance is so critical and the compiler
is unable to optimize the conversion itself.



Instead, I think that the following extension would be more useful.

When we use newtype to create a new numeric type, we must make
instances of various classes ourselves. The deriving mechamism saves
us from boring Eq and Ord instances, but will not help with Num or
Integral even if they are "obvious".

Proposal. Allow specifying any single-parameter type class in the
deriving list of a newtype, provided that method types agree with
the following rules, the type under the newtype is an instance of
that class, and the newtype is an instance of all superclasses.

Each method is derived from the corresponding method for the oldtype.
Implementation is easier than specification of exact rules :-)
The intent is that the same physical code will work for the newtype
as well. To obtain this, the implementation of the method is formally
converted, as driven by old and new types of the method.

An expression e of type t is converted to C[e] thus:

- If t does not mention the oldtype, the target type is the same and
  C[e] = e.

- If t is the oldtype, then C[e] = N e, where N is the newtype's
  constructor.

- If t is a function type, then C[e] = e `seq` \x -> C[e (C'[x])],
  where C' is the dual conversion, from the new type to the old type.

- If t is a tuple type, then
  C[e] = case e of (e1,...,eN) -> (C[e1],...,C[eN]).
  This is needed e.g. for Integral's quotRem.

- If t is the list type, then C[e] = map (\x -> C[x]) e.
  This is needed e.g. for Enum's enumFromTo.

- Otherwise the class is not derivable.

So it works for all Prelude type classes. The only conflict with
current derivings is for Show and Read, which is unfortunate because
it's not obvious which case is needed and I'm not sure how to
resolve it.

-- 
 __("<    Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/              GCS/M d- s+:-- a23 C+++$ UL++>++++$ P+++ L++>++++$ E-
  ^^                  W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP+ t
QRCZAK                  5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-


Reply via email to