rbs icon indicating copy to clipboard operation
rbs copied to clipboard

[Feature request] Introduce constant type

Open ybiquitous opened this issue 4 years ago • 7 comments

When I've recently opened PR to add signatures of the Parallel gem on the ruby/gem_rbs_collection repository, I encounter the following difficulty:

# Ruby code
items = [1, 2, 3]
Parallel.all?(-> { items.pop || Parallel::Stop }) { |item| item.size == 1 }

# RBS (short version)
module Parallel
  Stop: Object

  # `T | Stop` should be better than `T | untyped`.
  def self.all?: [T] (Enumerable[T] | (^() -> T | untyped) array) { (T) -> boolish } -> bool
end

As you see above, we now cannot use Parallel::Stop as a type.

Supporting such a type signature might be useful, but what do you think?


This proposal is thanks to @pocke. Please refer to https://github.com/ruby/gem_rbs_collection/pull/21#discussion_r587286192 for details.

ybiquitous avatar Mar 07 '21 09:03 ybiquitous

Yes, Parallel::Stop is not a type here. I don't think we can introduce a feature to use constants as types...

Do you know if some languages allow this?

soutaro avatar Mar 07 '21 13:03 soutaro

Do you know if some languages allow this?

Umm..., I'm not sure, but TypeScript does not seem to support such a type at least:

image

https://www.typescriptlang.org/play?ssl=1&ssc=1&pln=7&pc=1#code/MYGwhgzhAEBiD29oG8BQ0PQgFzNglsNAEJgBO0AvNAIzqYBGYAXgBTkDmAXCeQJQ8AbvHwATFPUyYyAU2wBXMgDtJ0AL6oNQA

This programming pattern like Parallel::Stop might not be common... 🤔

ybiquitous avatar Mar 08 '21 00:03 ybiquitous

One idea is to introduce new opaque type feature that allows writing:

module Parallel
  type stop          # No right hand side; defines new type that's not equivalent to anything else.
  Stop: stop

  def self.all?: [T] (Enumerable[T] | (^() -> T | stop) array) { (T) -> boolish } -> bool
end

soutaro avatar Mar 08 '21 14:03 soutaro

@soutaro Introducing an Opaque Type sounds like an interesting idea!

Considering a type without assignment as an opaque type seems sufficient for this case (Parallel::Stop), but if we would introduce an opaque type, it seems to me that there are more things to consider.

For an example of Flow, the opaque keyword is used.

Also, for an example of Swift, the some keyword is used.

ybiquitous avatar Mar 09 '21 08:03 ybiquitous

@ybiquitous I think the type syntax without equation is brought from signature declaration of OCaml.

  • https://caml.inria.fr/pub/docs/manual-ocaml/moduleexamples.html#s%3Asignature

The problem is that if we can introduce the concept of internal <=> external. I don't think it makes much sense compared to the complexity required for it...

soutaro avatar Mar 12 '21 05:03 soutaro

Oh, the syntax comes from OCaml. I understand. 🙆‍♂️

The problem is that if we can introduce the concept of internal <=> external. I don't think it makes much sense compared to the complexity required for it...

That's a hard trade-off. If such a pattern like Parallel::Stop is not common, it seems unreasonable to me to introduce a new syntax... 🤔

ybiquitous avatar Mar 12 '21 11:03 ybiquitous

Just FYI TypeScript does allow this, you just have to tell to use the typeof that specific property (your syntax had it looking just for a global Bar property):

class Foo {
    static Bar = 1
    baz(arg: typeof Foo['Bar']): void {
        return
    }
}

https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8BQ0PQgFzNglsNAEJgBO0AvNAIzqYBGYAXgBTkDmAXNNgJ4AHAKbwAZnEQBtAOSky0gLoBKHgDd4+ACYp6mTGSHYArmQB2u6AF9U1oA

image

G-Rath avatar Jun 07 '21 04:06 G-Rath