Skip to content

[Feature Request] Allow (T) to be treated as T #1476

Description

@NoahStoryM

Is your feature request related to a problem? Please describe.

I noticed that type constructors with zero parameters are sometimes treated inconsistently depending on context.

For example:

> (define-type (Nat) (Natural))
string:1:19: Type Checker: Error in macro expansion -- parse error in type;
 bad syntax in type application: expected a type constructor
  given a type: Nonnegative-Integer
  in: (Natural)
 [,bt for context]
> (define-type (Nat) Natural)
> (ann 123 (Nat))
string:1:9: Type Checker: Error in macro expansion -- parse error in type;
 bad syntax in type application: expected a type constructor
  given a type: Nonnegative-Integer
  in: (Nat)
 [,bt for context]
> (ann 123 Nat)
- : Integer [more precisely: Nonnegative-Integer]
123
> (: add (∀ () (→ Real Real Real)))
> (:print-type add)
(-> Real Real Real)
> (inst add)
string:1:6: Type Checker: Cannot instantiate non-polymorphic type (-> Real Real Real)
  in: add
 [,bt for context]

Similarly, for structures:

> (struct () S ())
> (ann (S) (S))
string:1:9: Type Checker: type cannot be applied
  type: S
  in: (S)
 [,bt for context]
> (ann (S) S)
- : S
#<S>

Typed Racket seems to treat (T) as an invalid type expression when T is a nullary type constructor. This inconsistency causes problems when writing macros that automatically generate type applications.

For example, in a macro like:

(define-record-type (t ...) T
  (make field-tag ...)
  T?
  field-spec ...)

which expands to:

(struct (t ...) struct-spec ...)
(: make (∀ (t ...) (→ t ... (T t ...))))

When (t ...) is (), the result type becomes (T), which triggers a type error — even though semantically it should just be T.

Describe the solution you'd like

I would like (T) to automatically expand to T when T is a nullary type constructor or just a type. This would make Typed Racket more consistent and make it easier to write macros that handle both parametric and non-parametric types uniformly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions