Re: Will too many paradigms addle my brain.



Joachim Durchholz <jo@xxxxxxxxxxxxx> writes:

> I'm starting from the classic statically-typed OO perspective, which
> upholds the following principles:
> * A class defines a type.
> * The LSP, i.e. that a subclass should define a subtype.
> * Class boundaries and module boundaries coincide.
> * Function calls are dispatched based on run-time type information.

I don't know a language-independent definition of a class.

LSP defines subtyping on the basis of substitutability. It can be
interpreted either as a definition of subtyping, or as a guideline
when to declare subtypes if they are declared explicitly. Subclassing
(inheritance of implementation) is a different tool, subclasses may
coincide with subtypes or not.

I hate languages where class boundaries and module boundaries must
coincide. For me modules are used as namespaces, splitting code into
files and separate compilation. (Some people believe that namespaces
should be decoupled from other uses of modules, but for me the ability
to selectively import and reexport names makes modules appropriate.)

Some functions dispatch their calls based on run-time type information.
Others do not.

My language Kogut reflects these views. I don't know whether it has
classes, it depends on the definition of a class. Subtyping, used for
dispatch, is declared explicitly, and it's the programmer's responsibility
to declare supertypes when it makes sense. When implementing a type,
you can delegate the behavior to another object or include "features"
(mixins), although I almost don't use this facility and prefer explicit
delegation through a field (with the functional style you have to change
many methods during wrapping anyway).

> Well, then floating-point and integer aren't in a subtype
> relationship, and they don't even compose.
>
> Integer and floating-point arithmetic are simply different
> operations, and there should be no automatic selection anyway.

I agree that they aren't in a subtype relationships, and disagree with
the rest. 2*x should return the number twice as big no matter whether
it's represented as an integer or as a floating point object.

> That depends on how you define the square root. Actually it's a
> two-parameter operation: the number of which we want the square
> root, and the precision that we want (machine epsilon or integral
> numbers, in that case).

Most of the time I don't want to specify the precision explicitly,
and with floating point there is little choice anyway. So my Sqrt
takes a single argument, like in all other languages.

A variable precision floating point type (currently unimplemented)
would receive the precision through a dynamic variable or use the
precision of the argument; I don't know which policy is better.
Often the same precision is used for several operations, so passing
it implicitly is more convenient. This doesn't need a new interface
of Sqrt.

>> If they have different types, there will probably be no method of
>> the given generic function for them, so you will get an error about
>> a generic function not applicable to some combination of types.
>> If they are not distinguished by types, the implementation of the
>> operation will have to detect this and throw an exception.
>
> Hmm... how does the framework decide what combinations are
> compatible and which are not?

I don't understand. It provides methods for types where the given
operation makes sense mathematically, and doesn't try to provide
cases where it makes no sense (like checking whether a ratio is even).
If only a part of a type is in the domain, for other values there
will be a runtime error (like division by zero).

It provides infinities which extend the domain of some operations
a bit. Inexact infinities are used to propagate overflow of the
representation, and exact infinities are primarily used to provide
a bound which is greater or less than anything else.

There are two kinds of operations with respect to default
implementations: some operations are defined by default through
conversion to different types, and should be provided by all types
which want their algorithm to be used (core operations); other
operations are defined in terms of core operations, e.g. Sqr x
is defined as x*x for types which don't provide their explicit
definition.

>> They have a sufficiently incompatible behavior that the intended
>> meaning of mixing them in the same operation is unclear. If it was
>> done anyway, the implementor of these numbers would have to decide
>> how to behave. But I'm not sure whether they should be considered
>> numbers at all.
>
> Numbers modulo some limit are numbers, sure enough. All the usual
> arithmetic laws hold.

It doesn't hold that 2*x==0 implies x==0. Generally they give
different results for operations already defined for plain integers,
so if they are considered numbers, they would have to be different
from existing integers, i.e. "2 (modulo 5)" is not a representation
of 2 but of an entirely different abstract thing, while float 2.0
for example *is* a representation of 2.

> It's also practically relevant because numbers modulo a power of two
> is particularly efficiently implementable on today's hardware.)

In the current implementation of Kogut they would be less efficient
than the standard INT, because they could not use the unboxed
representation, which is already taken by small ints. The only case
where they could be more efficient is representing numbers just above
the small int range (signed machine word minus one bit), where
a heap-allocated fixed-size word is faster than a general bignum.
Of course in a hypothetical optimizing implementation this could be
different.

--
__("< Marcin Kowalczyk
\__/ qrczak@xxxxxxxxxx
^^ http://qrnik.knm.org.pl/~qrczak/
.



Relevant Pages

  • Re: Rounding of the double
    ... John von Neumann suggested that only fixed-point integers should be used because floating ... If you choose your representation as double, then you have to live with the consequences. ... you can never get precision in any computation on a computer than involves ... MVP Tips:http://www.flounder.com/mvp_tips.htm- Hide quoted text - ...
    (microsoft.public.vc.mfc)
  • Re: Subplot frustration
    ... an artifice of ML's representation of the internal handle as a default Double... ... converting to decimal representations of floating point numbers. ... to a decimal string with no loss of precision. ... My other supposition is that the "handle graphics" package was a product not developed inside TMW, but that again is an assumption. ...
    (comp.soft-sys.matlab)
  • Re: What I can to do with old PL/1 code?
    ... >> I have IBM Visual Age PL/1 compiler, ... > issues related to limitations on precision and representation of real ... > the same binary precision for all floating point numbers. ...
    (comp.lang.pl1)
  • Re: Rounding of the double
    ... When in doubt, trust the representation. ... digits precision", the first rule is that only the binary bits matter. ... The formal specification of floating point precision is usually expressed as ±1 LSB (Least ...
    (microsoft.public.vc.mfc)
  • Re: Will too many paradigms addle my brain.
    ... Class boundaries and module boundaries coincide. ... If syntax lets the compiler infer that a type is a subtype of some other given type, then that subtype property should also hold semantically. ... 2*x should return the number twice as big no matter whether it's represented as an integer or as a floating point object. ... the number of which we want the square root, and the precision that we want. ...
    (comp.lang.functional)