j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Type aliasing: some options #75

Open klausler opened 5 years ago

klausler commented 5 years ago

It would be useful to be able to establish a name as an alias for a type so that the name could be (for example) USE-associated. This is presently possible for derived type names, of course, but not intrinsic types, and perhaps only aliases for intrinsic types need to be supported.

The syntax could be something like TYPE(type-spec), ALIAS :: name or TYPE :: name => type-spec.

Use case (sorry):

MODULE M
  TYPE(REAL(4)), ALIAS :: M_TYPE
END MODULE
USE M, ONLY: M_TYPE
TYPE(M_TYPE) :: X ! same as REAL(4) :: X

Perhaps type parameters could be deferred

Additionally or alternatively: if type aliases could be defined as pseudo-components of derived types, that would likely be sufficient, and may well be more useful; e.g.,

  TYPE :: DT(K)
    INTEGER, KIND :: K
    TYPE(REAL(K)), ALIAS :: R ! or TYPE :: R => REAL(K)
    TYPE(R), ALLOCATABLE :: A(:,:)
    ...
  END TYPE
  TYPE(DT(4)) :: X
  TYPE(DT(4)%R) :: Y
  TYPE(X%R) :: Z

Last, if it were possible to inquire about the type of an entity and use that type in another declaration, that may also suffice. Something like TYPE(OF(expr)) and (for derived types) CLASS(OF(expr)). Then one could gain the same effect as a type alias through the use of a prototype entity, similar to decltype in C++.

None of the syntax above is particularly important, and implementation of any/all of these would be straightforward.

Apologies in advance to any who may think these ideas are insufficiently developed before being described here. I would rather lay out the various options that I know about for discussion than propose a fully elaborated design of the wrong alternative.

klausler commented 5 years ago

A related feature to also consider: conditional typing via TYPE(IF(constant-logical-expr,t1,t2)) and CLASS(IF(constant-logical-expr,t1,t2)) or some other syntax.

rweed commented 5 years ago

I've always wondered why we couldn't put further restrictions on pointers so they can only act as aliases for other variables (ie, can't be allocated and can't point to array segments). I've found in refactoring old code that its sometimes convienent to make existing old variable names contiguous pointers (usually something in an EQUIVALENCE statement) because that is easier for me than trying to do ASSOCIATE on 20 or 30 variables. I guess CONTIGUOUS probably does the same thing. While my preference would just be an ALIAS attribute instead of having to reference POINTER at all (ie REAL, ALIAS :: someValue(:,:)) I could live with just REAL, POINTER, ALIAS :: someValue(:,:)

FortranFan commented 5 years ago

@rweed wrote:

I've always wondered why we couldn't put further restrictions on pointers so they can only act as aliases for other variables (ie, can't be allocated and can't point to array segments). I've found in refactoring old code that its sometimes convienent to make existing old variable names contiguous pointers (usually something in an EQUIVALENCE statement) because that is easier for me than trying to do ASSOCIATE on 20 or 30 variables. I guess CONTIGUOUS probably does the same thing. While my preference would just be an ALIAS attribute instead of having to reference POINTER at all (ie REAL, ALIAS :: someValue(:,:)) I could live with just REAL, POINTER, ALIAS :: someValue(:,:)

@rweed, it does not appear your comments pertain to the issue in this thread.

FortranFan commented 5 years ago

An idea long considered by the J3 Fortran committee appears to be "New Types from Existing" that is supposed to include support for the kind of aliasing indicated in the original post of this thread:, see the following for a couple of recent discussions: https://j3-fortran.org/doc/year/18/18-113r1.txt https://j3-fortran.org/doc/year/18/18-255.txt

Unfortunately the work toward developing a facility of "New types from existing" is another one of those items that keeps getting pushed back by the committee, the last it was discussed they came away with "No action, understand the desire but contradiction between different bits; generic resolution would be ambiguous, intrinsic operators interconnect in interesting ways (math functions, intrinsics, etc)"

I personally like the idea of a TYPE ALIAS, both user-defined and also some intrinsic ones. On another issue #13, there is some back and forth between the use of REALNN named constants for supported kinds in a processor toward floating-point types vis-a-vis the use of SELECTED_REAL_KIND intrinsic function (but not to forget the IEEE_SELECTED_REAL_KIND one!).

As I wrote in a separate thread at comp.lang.fortran: With near-universal support of IEEE 754 floating-point arithmetic with current processors, what Fortran can do for its practitioners is to offer SHORT-HAND notation to more easily consume the IEEE 754 number format in codes.

For heaven's sake, the Fortran standard committee would do well to introduce INTRINSIC ALIASes of, say, FP32, FP64, FP128 that map to the corresponding 32-bit, 64-bit, and 128-bit formats (i.e., "real(KIND=ieee_selected_real_kind(P=..,R=.., RADIX=..)") that are listed in the IEEE 754 standard in great detail and which have been supported by all the processors for nearly 30 years now. This is so that a young, bright middle-schooler can readily start doing 'formula translation' in Fortran with IEEE 754 formats like so

    fp64, parameter :: Rgas = ..
    fp64 :: T, P, density
    ..
    density = P/Rgas/T

instead of the verbose and ill-communicated 'canon':

    integer, parameter :: RK = ieee_selected_real_kind( p=..)
    real(kind=RK), parameter :: Rgas = ..
    real(kind=RK) :: T, P, density
    ..
    density = P/Rgas/T
rweed commented 5 years ago

@FortranFan sorry, you are correct. I didn't read the original post close enough. However, what is being proposed is similar to my suggestion about making the values returned by the selected_..._kind functions and the intrinsic KIND value in ISO_FORTRAN_ENV (REAL32, INT32, etc) unique. The ISO_FORTRAN_ENV variables in particular are then effectively the type aliases used in the current context. in particular instead having to type

type(real(REAL64) :: areal type(integer(INT32) :: anint

you only need

type(REAL64) :: areal type(INT32) :: anint

FortranFan commented 5 years ago

@rweed wrote:

.. what is being proposed is similar to my suggestion about making the values returned by the selected_..._kind functions and the intrinsic KIND value in ISO_FORTRAN_ENV (REAL32, INT32, etc) unique. ..

@rweed, do note what is proposed in the J3 papers (e.g., 18-255) is more comprehensive, it allows an ALIAS for intrinsic as well as user-defined types.

Separately, as you know well the standard since Fortran 90 has not mandated "unique" values for the KINDs across all intrinsic types. That's nearly 30 years now. And there are quite a few processor implementations where the KINDs are not unique. So it appears infeasible now, in addition to being of limited value, to include something like this in the standard.

aradi commented 5 years ago

@FortranFan As for your example with the fp64 type, how would the parameter assignment work? I find

integer, parameter :: wp = selected_real_kind(...)
real(wp), parameter :: myconst = 0.1234_wp

maybe somewhat verbose, but consistent. If you used fp64 instead

fp64, parameter :: myconst = 0.1234_wp

looks rather inconsistent and confusing to me. Of course, you could also introduce fp64 as a kind value, then

fp64, parameter :: myconst = 0.1234_fp64

would be at least consistent again, but not necessarily less verbose than the original one.

FortranFan commented 5 years ago

@aradi wrote:

@FortranFan As for your example with the fp64 type, how would the parameter assignment work? ..

@aradi , thank you for your interest.

My vision is by the time something like a TYPE ALIAS facility makes it into the language, Fortran would have great strides in what it offers the practitioners of Fortran with LITERAL CONSTANTS, perhaps along the lines of ideas in #78, so much so the issue of type and kind of "magic numbers" become intuitively obvious from the "context" (e.g., what the coders has enabled in the scoping unit) as they do with beautiful formulae in science and math, that codes in Fortran are allowed to get closer and closer to formula translation and achieve blackboard abstraction. With that in mind, my hope is one should be simply be able to do the following with no risks or dangers in terms of type, kind mismatch and any consequent loss of precision, etc.:

! The scoping unit for the statement below shall be able to state the KIND for the
! literal is the same as that of the named constant
fp64, parameter :: myconst = 0.1234

I do think Fortran needs to advance beyond the _wp kind of suffix/prefix in literal constants.

klausler commented 5 years ago

I should add that my conception of type aliases are true aliases, not a newtype in the sense of Haskell. An alias should work exactly as if the type to which it resolves had been specified instead, and there must be no consequences to the semantics of generic resolution, intrinsic operators and functions, I/O, or anything else.

vansnyder commented 2 years ago

I haven't seen a use case for type aliases that cannot be satisfied by new types from existing ones. One use case for new types is the example of a code designed to run with different precisions. If you declare two kind type parameters, say SELECTED_REAL_KIND(7) and SELECTED_REAL_KIND(14), create procedures having REAL variables with those kinds, and join them with a generic interface block, all is well -- until your code arrives in a processor where those inquiry functions have the same value. It won't even compile, let alone get generic resolution right. If you could declare different types, not type aliases and not different kinds of the same type, there would be no problem.

This proposal foundered at Tokyo in 2019 when Malcolm asked "what would be the kind of the result of a mixed type operation such as multiplication?" Of course the answer was "a simple generalization of the rules in Clause 10" (10.1.9.3 in 22-007r1) but that didn't carry the day.