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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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