Mon, 24 Jan 2000 07:49:30 -0800, Simon Peyton-Jones <[EMAIL PROTECTED]> pisze:

> (A) Make them defined for any n.  If n < 0, do something reasonable:
>         take:   give empty list
>         drop:   give whole list
> 
> (B) Make them defined for n > length xs, but fail for n < 0.

I vote for (B) or (A), in that order.

Mon, 24 Jan 2000 14:37:41 -0500 (Eastern Standard Time), S. Alexander Jacobson 
<[EMAIL PROTECTED]> pisze:

> Why not do what python does?
> 
> drop -2 -- drops the last 2 elements from the list
> take -2 -- grabs the last 2 elements from the list

Please no.

I hate the design used in the K language: when thinking how to name a
function, find an existing function name which in all or almost all
current meanings use a disjoint domain of arguments, and reuse that
name. Here it is not as extreme as in K, but IMHO still not nice.

Using otherwise illegal values to represent a modified behavior was
needed in languages with poor type systems, without things like Maybe,
tuples, higher order functions and convenient algebraic datatypes. An
elegant language like Haskell does not need to provide parametrization
using such ways.

I believe it would create more problems by not catching some bugs
than convenience by allowing reusing a name for various purposes.

When something has to be done at runtime due to a library design,
but in principle could be done at compile time, I often feel that
it's a symptom of a bad design. It does not matter that the actual
overhead is quite small in practice. I talk about elegance.

Values should be represented in appropriate types. It's good when
the structure of a type corresponds to the logical structure of a
value, which is not the case when an integer represents a positive
integer plus a boolean value in its sign bit.

I even wish it was possible to specify regular expressions by an
algebraic type instead of strings to be parsed. It's an unfortunate
situation when my principles can create less readable code. Well,
so we could have regexps both ways; parsed regexps are also useful
when they come from files. We should have regexps as an appropriate
datatype and a separate parsing function for convenience.

A value may reside in a bigger type than actually needed when either
specifying the right type is impossible or hard or very inconvenient
(like nonnegative integers - our case), or when it would be often
impossible to statically enforce the requirement anyway (so I don't
propose a separate type of nonempty lists for tail's argument),
or when the protocol must be typeless and extensible in nature
(like talking to a newsserver - we can only create typeful wrappers
locally). But when it unfortunately happens that a type is too big,
we notice it and it does not mean that we should reuse the invalid
values for something else.

Trying to encode too much in invalid values, or overloading too much,
or generally using inappropriate types, may cause ambiguities or create
special cases. AFAIR NDos uses negative offsets for the right end of
a string, but also starting from 0, so -0 is the rightmost character.
Perl syntax is very often ambiguous, trying to resolve to "more common"
possibilities then. Escaping various special characters is used in
many contexts.

Generating an error, even fatal, can be more appropriate than trying
to produce any sensible result from whatever we have - to detect bugs
early (unless it would be hard to enforce proper values, like floating
point division by 0 or parsing something).

Overloading take and drop would make sense when the decision about
how to proceed would be often done at a different place than the
usage of these functions, i.e. when the overloaded function was used
polymorphically. I think it's not the case. And when we really want
to represent various kinds of sublists in a value, it's not general
enough that way. If at some place you don't statically know from which
end to cut, you probably want to be able to specify other variants too,
like "from second to the one before the last" or "the first half".

So I say NO to printf, to Perl's open function (which encodes
a dozen of functions in the string representing the filename and
requires horrible things to disable special interpretation of special
characters), to representing enumerations in character or integer
types (Haskell's Ordering is better than C's any integer <0, ==0,
>0), to choosing a function basing on its _name_ in a runtime value
(in a String type), to -1 meaning EOF or infinity etc. I prefer
existential quantification to Dynamic.

Strong typing is great. I'm writing a web browser in Haskell for an
assignment. I've already made the HTML parser (automatically produced
from a DTD). The abstract syntax is statically typed, with separate
types for each element.

The above elaboration is longer than the subject needs. Sorry, I was
trying to verbalize my thoughts in several ways.

-- 
 __("<    Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/              GCS/M d- s+:-- a22 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