Skip to content

Provide a way to define tuple sucseccsion types  #4413

Open
@Gozala

Description

@Gozala

There are some instances where it would be really useful to have a way to define a succession type for an existing tuple. I presumed something like this would work, but unfortunately it does not:

type Prepend <first, rest> = [first, ...rest]

Here an example where something like this is necessary:

type State <values> = {
  chunks Array<string>,
  parsed: values
}

interface Parser<a, b> {
  parse(state: State<a>): Array<State<b>>
}

class VariableParser<a, b> implements Parser<a, [b, ...a]> {
  read: string => ?b
  name: string
  constructor(name: string, read: string => ?b) {
    this.name = name
    this.read = read
  }
  parse({ chunks, parsed }: State<a>): Array<State<[b, ...a]>> {
    if (chunks.length === 0) {
      return []
    } else {
      const [first, ...rest] = chunks
      const value = this.read(first)
      if (value != null) {
        return [
          {
            chunks: rest,
            parsed: [value, ...parsed]
          }
        ]
      } else {
        return []
      }
    }
  }
}

Right now only option to do something along those lines requires either usage of trees: so instead of Parser<a, [b, ...a]> -> Parser<a, [b, a]> or functions Parser<a, a => b> but both options lead to unpleasant interfaces to use and really confusing error messages. Here is a complete example to illustrate this case, here is a tiny summary:

const url = "/user/bob/comments/42"
const userCommentParser = segment("user")
  .chain(string("name"))
  .segment("comments")
  .chain(integer("id"))

parseAs(userCommentParser, (name: string, id: number) => ({ name, id }), url)

parseAs(userCommentParser, (name: string, id: string) => ({ name, id }), url) // <- fails due to type mismatch for `id` argument
    230: parseAs(userCommentParser, (name: string, id: string) => ({ name, id }), url)
         ^ function call. Function cannot be called on any member of intersection type
    167:   <a, out>(parser: Parse<[a, null]>, (a) => out, url: string): ?out,
           ^ intersection

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions