Just an idea I had:

When you define a module that is supposed to serve as an ADT, you can do it
three ways: using "datatype", "newtype" or "type".  (OK, it's not really
an ADT if you use "type".)  Such a module defined using "newtype" looks
essentially like the same module defined using "type" except that each
function unpacks the argument type first, and packs it back again before
it returns it.  In other words:

  fun_using_newtype = pack . fun_using_type . unpack

Here's an example.

  type Set a = [a]
  union xs ys = nub (xs ++ ys)

  newtype Set' a = Set' (Set a)
  union (Set' xs) (Set' ys) = Set' (union xs ys)

the translation from Set to Set' is almost mechanical, and one can imagine
a program that takes as input a "type" ADT and transforms it into a "newtype"
ADT.  The immediate problem I see is distinguishing between uses of [] as a
set, and [] as a list.  For example:

  unionMany :: [Set a] -> Set a
  unionMany sets = foldr union singleton sets

[Set a] = [[a]], but we would want to transform this into [Set' a] rather than
Set' (Set' a).

However, if the transforming program took into account the information in the
type signature (for unionMany, it would notice that the user used the type
synonym for the inner list only), it could make pretty good guesses about which
arguments and results to unpack or pack.

Since the additional constructor applications and pattern matches in "newtype"
ADTs makes them harder to read and write, I think it is useful to be able to
generate them automatically from simpler, "type" ADTs.  Assuming that there
are no other problems, maybe one could define some sort of derivation
mechanism for such ADTs so that they would be imported abstractly:

  import Set'(newtype Set', union', unionMany')
         = abstract Set(type Set, union, unionMany)

(I'm using the proposed Standard Haskell syntax for imports which eliminates
the special identifier "as" in favor of "=" and mentions the declaration
keywords used for types.)

-- FC




Reply via email to