Language extension proposal

Hal Daume t-hald@microsoft.com
Wed, 25 Jun 2003 08:48:12 -0700


I'm not sure this is really necessary (at least syntax-wise).

We can do something like:

> data T a
> class Trait a where { trait :: T a -> Int }
>=20
> instance Trait Int  where { trait _ =3D 0 }
> instance Trait Char where { trait _ =3D 1 }

As far as I can tell with the various --ddump-* flags, the compiler
hasn't yet figured out that the argument to trait is useless (i.e., it
keeps it in there).

However, from a sanity point of view, I much prefer to write my "useless
arguments" like this; that way at least *I* know that they'll never be
evaluated.  I suppose the only thing that could go wrong is someone
writing:

> instance Foo Bool where { trait x =3D x `seq` 1 }

in which case it would be wrong for the compiler to get rid of this
argument.

I suppose that your solution gets rid of this problem by relizing that
seq doesn't have absent demand on its argument (quite the opposite, in
fact).

Of course, the powers that be can weight in on this, and I'm sure that
you're aware of the phantom type solution, but I figured I'd post anyway
so that others can get a look at types like this for their own
benefit...

--
 Hal Daume III                                   | hdaume@isi.edu
 "Arrest this man, he talks in maths."           | www.isi.edu/~hdaume


> -----Original Message-----
> From: haskell-admin@haskell.org=20
> [mailto:haskell-admin@haskell.org] On Behalf Of Andrew J Bromage
> Sent: Tuesday, June 24, 2003 9:18 PM
> To: haskell@haskell.org
> Subject: Language extension proposal
>=20
>=20
> G'day all.
>=20
> I've been toying with an idea for a small language extension, and I
> was curious what you all think of this.
>=20
> As a motivating example, consider the following standard typeclass:
>=20
> 	class Bounded a where
> 	    min :: a
> 	    max :: a
>=20
> This is an example of what I refer to as a "traits typeclass" (by
> analogy to traits classes, well-known to C++ programmers).  The idea
> is that you want to specify certain properties/operations which depend
> on a _type_, rather than any particular value of that type.
>=20
> Another example is floating point format information, like the
> information in C's <float.h>.  One might implement this as:
>=20
> 	class (Bounded a) =3D> FloatTraits a where
> 	    epsilon :: a		-- OK
> 	    mantissaDigits :: Int	-- Not OK!
>=20
> For obvious reasons, the declaration of mantissaDigits is not valid
> Haskell.  Instead, you might do something like this:
>=20
> 	class FloatTraits a where
> 	    mantissaDigits :: a -> Int
>=20
> 	instance FloatTraits Float where
> 	    mantissaDigits _ =3D 24
>=20
> 	instance FloatTraits Double where
> 	    mantissaDigits _ =3D 53
>=20
> and invoke it as, say:
>=20
> 	mantissaDigits (undefined :: Float)
>=20
> A decent strictness analyser can tell if an argument to some function
> is always unused (in GHC core terminology, this means its demand is
> "absent") and thus avoid passing the argument at all.  However, it is
> currently impossible to tell if this is true all instances of a
> typeclass.  What I would like is some annotation that I can=20
> use to tell
> my compiler that this argument of this method is always unused, no
> matter what instance it resolves to.
>=20
> My proposal is to grab a new punctuation symbol (I will use '~' as
> an example) to sit alongside the GHC extension use of '!'.  Where '!'
> means that an argument may be evaluated before calling a function, '~'
> means than an argument may be ignored by the callee.  So in the above
> example, I can write:
>=20
> 	class FloatTraits a where
> 	    mantissaDigits :: ~a -> Int
>=20
> Now this marker is not as simple to implement as '!'.  The strict
> marker is advisory; if you stripped all '!'s from your program, it
> would still have the same static semantics.  Not so with '~', which
> must be statically checked.
>=20
> However, the static analysis is pretty trivial, except for the
> problem of inference.  Basically, if a variable has absent demand,
> it a) can't be pattern matched on (unless the pattern is a variable,
> of course), and b) can't be passed as an argument to a function
> (including a data constructor) which doesn't also treat that argument
> as having absent demand.
>=20
> I therefore propose that the marker not be inferred for top-level
> definitions, or at least for exported definitions.  If you declare it,
> it's checked, but otherwise it's not.  In addition, any calls that you
> pass a variable with absent demand to must themselves have the marker
> declared explicitly in their type signatures.
>=20
> There may also be an argument for extending '~' to data constructors,
> in the same way that H98 uses '!'.  This would allow parameters with
> absent demand to be stored in data structures.  I can't think of a
> use for this right now, but it shouldn't be too much harder to add.
>=20
> What do you all think?  Useful?  Not worth the effort?
>=20
> Cheers,
> Andrew Bromage
> _______________________________________________
> Haskell mailing list
> Haskell@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell
>=20