{"action":"created","issue":{"url":"https://api.github.com/repos/ericelliott/rtype/issues/80","repository_url":"https://api.github.com/repos/ericelliott/rtype","labels_url":"https://api.github.com/repos/ericelliott/rtype/issues/80/labels{/name}","comments_url":"https://api.github.com/repos/ericelliott/rtype/issues/80/comments","events_url":"https://api.github.com/repos/ericelliott/rtype/issues/80/events","html_url":"https://github.com/ericelliott/rtype/issues/80","id":148385294,"number":80,"title":"generic types - syntax comparison","user":{"login":"maiermic","id":8530117,"avatar_url":"https://avatars.githubusercontent.com/u/8530117?v=3","gravatar_id":"","url":"https://api.github.com/users/maiermic","html_url":"https://github.com/maiermic","followers_url":"https://api.github.com/users/maiermic/followers","following_url":"https://api.github.com/users/maiermic/following{/other_user}","gists_url":"https://api.github.com/users/maiermic/gists{/gist_id}","starred_url":"https://api.github.com/users/maiermic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maiermic/subscriptions","organizations_url":"https://api.github.com/users/maiermic/orgs","repos_url":"https://api.github.com/users/maiermic/repos","events_url":"https://api.github.com/users/maiermic/events{/privacy}","received_events_url":"https://api.github.com/users/maiermic/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ericelliott/rtype/labels/proposal","name":"proposal","color":"383838"},{"url":"https://api.github.com/repos/ericelliott/rtype/labels/ready","name":"ready","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":26,"created_at":"2016-04-14T14:47:11Z","updated_at":"2016-05-04T19:26:51Z","closed_at":null,"body":"# Overview and comparison of generic type syntax proposals\r\n\r\nThis issue lists and compares several syntax proposals that have been proposed and initially discussed in issue #55. It should help to come to a decision which syntax proposal should be used.\r\n\r\n**Note:** The following aspects have not been discussed yet and are not part of this overview/comparison:\r\n - variance (covariant, contravariant and invariant), see issue #81\r\n - constraints on generic type arguments, see issue #82\r\n\r\n\r\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\r\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\r\n## Table of Contents\r\n\r\n- [Examples](#examples)\r\n  - [Functions](#functions)\r\n    - [Transform](#transform)\r\n    - [Filter](#filter)\r\n    - [Map](#map)\r\n  - [Interface](#interface)\r\n- [Syntax proposals](#syntax-proposals)\r\n  - [Angle Brackets Syntax](#angle-brackets-syntax)\r\n    - [single-line without colons](#single-line-without-colons)\r\n    - [single-line with colons](#single-line-with-colons)\r\n    - [multiline with colons](#multiline-with-colons)\r\n    - [multiline with curly brackets](#multiline-with-curly-brackets)\r\n  - [Square Brackets Syntax](#square-brackets-syntax)\r\n    - [single-line without colons](#single-line-without-colons-1)\r\n    - [single-line with colons](#single-line-with-colons-1)\r\n    - [multiline with colons](#multiline-with-colons-1)\r\n    - [multiline with curly brackets](#multiline-with-curly-brackets-1)\r\n  - [Parentheses Syntax](#parentheses-syntax)\r\n    - [single-line without colons](#single-line-without-colons-2)\r\n    - [single-line with colons](#single-line-with-colons-2)\r\n    - [multiline with colons](#multiline-with-colons-2)\r\n    - [multiline with curly brackets](#multiline-with-curly-brackets-2)\r\n  - [Whitespace Syntax](#whitespace-syntax)\r\n    - [single-line without colons](#single-line-without-colons-3)\r\n    - [single-line with colons](#single-line-with-colons-3)\r\n    - [multiline with colons](#multiline-with-colons-3)\r\n    - [multiline with curly brackets](#multiline-with-curly-brackets-3)\r\n- [Comparison of syntax proposals](#comparison-of-syntax-proposals)\r\n  - [Angle Brackets Syntax](#angle-brackets-syntax-1)\r\n    - [Advantages](#advantages)\r\n    - [Disadvatages](#disadvatages)\r\n  - [Square Brackets Syntax](#square-brackets-syntax-1)\r\n    - [Advantages](#advantages-1)\r\n    - [Disadvatages](#disadvatages-1)\r\n  - [Parentheses Syntax](#parentheses-syntax-1)\r\n    - [Advantages](#advantages-2)\r\n    - [Disadvatages](#disadvatages-2)\r\n  - [Whitespace Syntax](#whitespace-syntax-1)\r\n    - [Advantages](#advantages-3)\r\n    - [Disadvatages](#disadvatages-3)\r\n\r\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\r\n\r\n\r\n## Examples\r\nIt might be easier for you to reason about syntax if you see some examples. Therefore, I will describe three function types `Transform`, `Filter` and `Map` and an interface type `Collection` in different syntaxes. I provide different writing styles of each syntax. For example, you might write `Filter` or `Map` with use of `Transform` or using an inline type expression instead.\r\n\r\n### Functions\r\nIn this section I describe the signature of the three generic function types. Further, I describe each type argument and give an example of an function implementation in JavaScript with its type as a comment.\r\n\r\n#### Transform\r\n**Name:** Transform\r\n\r\n**Type arguments:** Input, Output\r\n\r\n**Signature:** `Transform(Input): Output`\r\n\r\n**Description:** A function that takes a value of type `Input` and returns a value of type `Output`.\r\n\r\n**Example:** The function `len` takes a `String` as parameter and returns its length as type `Number`. Thus it is of type `Transform` where `Input` is `String` and `Output` is `Number`.\r\n```JS\r\n// Transform(String): Number\r\nfunction len(str) {\r\n  return str.length;\r\n}\r\n```\r\n\r\n#### Filter\r\n**Name:** Filter\r\n\r\n**Type arguments:** Element\r\n\r\n**Signature:** `Filter(Element => Boolean, Element[]): Element[]`\r\n\r\n**Description:** Filter elements of type `Element` in an array. Take a function of type `Element => Boolean` (is equivalent to `Transfrom(Element): Boolean`) as first parameter. Takes array of type `Element[]` as second parameter. Returns an array of type `Element[]`.\r\n\r\n**Example:** An generic implementation might look like this:\r\n```JS\r\n// Filter(Element => Boolean, Element[]): Element[]\r\nfunction filter(predicate, elements) {\r\n  return elements.filter(predicate);\r\n}\r\n```\r\nThe generic type argument `Element` has to be inferred from the passed arguments of the `filter` call.\r\n```JS\r\n// Transform(Number): Boolean\r\nfunction isEven(x) {\r\n  return x % 2 === 0;\r\n}\r\n\r\n// Transform(String): Boolean\r\nfunction isShort(str) {\r\n  return str.length < 4;\r\n}\r\n\r\n// Number[]\r\nvar numbers = [1, 2, 3, 4];\r\n\r\n// String[]\r\nvar strings = [\"rtype\", \"is\", \"cool\"];\r\n\r\n// Filter(Number => Boolean, Number[]): Number[]\r\nfilter(isEven,  numbers); // [2, 4]: Number[]\r\n\r\n// Filter(String => Boolean, String[]): String[]\r\nfilter(isShort, strings); // [\"is\"]: String[]\r\n\r\n// type conflicts if incompatible types are use as type argument `Element`\r\nfilter(isEven,  strings); // Error: In \"Filter\" the first type argument \"Element\" couldn't match both (incompatible) types Number and String\r\nfilter(isShort, numbers); // Error: In \"Filter\" the first type argument \"Element\" couldn't match both (incompatible) types String and Number\r\n```\r\n\r\n#### Map\r\n**Name:** Map\r\n\r\n**Type arguments:** Input, Output\r\n\r\n**Signature:** `Map(Input => Output, Input[]): Output[]`\r\n\r\n**Description:** Filter elements of type `Element` in an array. Take a function of type `Element => Boolean` (is equivalent to `Transfrom(Element): Boolean`) as first parameter. Takes array of type `Element[]` as second parameter. Returns an array of type `Element[]`.\r\n\r\n**Example:** Map elements of type `Input` to type `Output`. Take a function of type `Input => Output` (is equivalent to `Transfrom(Input): Output`) as first parameter. Takes array of type `Input[]` as second parameter. Returns an array of type `Output[]`.\r\n```JS\r\n// Map(Input => Output, Input[]): Output[]\r\nfunction map(transform, elements) {\r\n  return elements.map(transform);\r\n}\r\n```\r\nThe generic type arguments `Input` and `Output` have to be inferred from the passed arguments of the `map` call.\r\n```JS\r\n// Transform(Number): Number\r\nfunction square(x) {\r\n  return x * x;\r\n}\r\n\r\n// Transform(String): Number\r\nfunction len(str) {\r\n  return str.length;\r\n}\r\n\r\n// Number[]\r\nvar numbers = [1, 2, 3, 4];\r\n\r\n// String[]\r\nvar strings = [\"rtype\", \"is\", \"cool\"];\r\n\r\n// Map(Number => Number, Number[]): Number[]\r\nmap(square, numbers); // [1, 4, 9, 16]: Number[]\r\n\r\n// Map(String => Number, String[]): Number[]\r\nmap(len,    strings); // [5, 2, 4]: Number[]\r\n\r\nmap(square, strings); // Error: In \"Map\" the first type argument \"Input\" couldn't match both (incompatible) types Number and String\r\nmap(len,    numbers); // Error: In \"Map\" the first type argument \"Input\" couldn't match both (incompatible) types String and Number\r\n```\r\n\r\n\r\n### Interface\r\n\r\nTo keep it simple, I describe an interface `Collection` that is satisfied by most common data structure objects (for example [Array](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array)).\r\n\r\n**Name:** Collection\r\n\r\n**Type arguments:** Element\r\n\r\n**Signature:**\r\n```\r\n// takes a type argument Element\r\ninterface Collection {\r\n  filter(Element => Boolean): Collection // with elements of type `Element`\r\n\r\n  // map is generic and takes an additional type argument `NewElement`\r\n  map(Element => NewElement): Collection // with elements of type `NewElement`\r\n}\r\n```\r\n\r\n**Description:** The interface `Collection` takes one type argument `Element` that is visible in the interface body. All elements in the data structure are of this type `Element`. A `Collection` has methods `filter` and `map`. They do the same as the functions `filter` and `map` I described in the chapter above, but since they are methods, the data structure is (implicitly) passed as `this` argument. Hence, the last argument of the corresponding function is dropped in the method.\r\n\r\n**Example:** Let's see some JavaScript code with `Array` as `Collection` to see the difference between the function `filter` and the method `filter`\r\n\r\n```JS\r\n// Number => Boolean\r\nfunction isEven(x) {\r\n  return x % 2 === 0;\r\n}\r\n\r\n// Number[]\r\n// Satisfies Collection where type argument Element is Number\r\nvar numbers = [1, 2, 3, 4];\r\n\r\n// Filter(Number => Boolean, Number[]): Number[]\r\nfilter(isEven, numbers); // [2, 4]: Number[]\r\n\r\n// numbers: Collection where type argument Element is Number\r\n// numbers.filter: (Number => Boolean): Number[]\r\nnumbers.filter(isEven);  // [2, 4]: Number[] which satisfies Collection where type argument Element is Number\r\n```\r\n\r\nand the difference between the function `map` and the method `map`:\r\n\r\n```JS\r\n// Transform(String): Number\r\nfunction len(str) {\r\n  return str.length;\r\n}\r\n\r\n// String[]\r\n// Satisfies Collection where type argument Element is String\r\nvar strings = [\"rtype\", \"is\", \"cool\"];\r\n\r\n// Map(String => Number, String[]): Number[]\r\nmap(len, strings); // [5, 2, 4]: Number[]\r\n\r\n// numbers: Collection where type argument Element is String\r\n// numbers.map: (String => Number): Number[]\r\nstrings.map(len);  // [5, 2, 4]: Number[] which satisfies Collection where type argument Element is Number\r\n\r\n```\r\n\r\n\r\n\r\n## Syntax proposals\r\nListed in the subchapters below are type declarations of the example types `Transform`, `Filter`, `Map` and `Collection` written in different variants of each syntax proposal. In all syntax proposals the name of the type is followed by its type arguments followed by its type definition. The difference is how type arguments are written. Are they enclosed in angle or square brackets, parentheses or are they only separated by whitespace. The different variants of a syntax vary in several aspects that might influence readability:\r\n\r\n - with or without colons after type signature\r\n - multi- vs. single-line\r\n - (some) type expressions enclosed in parentheses: `Input => Output` vs. `(Input) => Output` vs. `(Input => Output)` used in a specific context\r\n - additional type argument declaration before or after the method name (here `map`)\r\n\r\n\r\n### Angle Brackets Syntax\r\nType arguments are enclosed in angle brackets and are separated by commas. This syntax is influenced by C++, Java, C# and TypeScript.\r\n\r\n\r\n#### single-line without colons\r\n\r\n##### Functions\r\n```\r\nTransform<Input, Output> Input => Output\r\n\r\nTransform<Input, Output> (Input) => Output\r\n\r\nTransform<Input, Output> (Input => Output)\r\n\r\nFilter<Element> (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter<Element> (Transform<Element, Boolean>, Element[]) => Element[]\r\n\r\nMap<Input, Output> (Input => Output, Input[]) => Output[]\r\n\r\nMap<Input, Output> (Transform<Input, Output>, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection<Element> {\r\n  filter(Element => Boolean) => Collection<Element>\r\n\r\n  filter(Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  <NewElement> map(transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  <NewElement> map(transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  <NewElement> map(Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection<Element> {\r\n  filter(Element => Boolean) => Collection<Element>\r\n\r\n  filter(Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  map<NewElement>(transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  map<NewElement>(transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  map<NewElement>(Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n\r\n#### single-line with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform<Input, Output>: Input => Output\r\n\r\nTransform<Input, Output>: (Input) => Output\r\n\r\nTransform<Input, Output>: (Input => Output)\r\n\r\nFilter<Element>: (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter<Element>: (Transform<Element, Boolean>, Element[]) => Element[]\r\n\r\nMap<Input, Output>: (Input => Output, Input[]) => Output[]\r\n\r\nMap<Input, Output>: (Transform<Input, Output>, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection<Element> {\r\n  filter: (Element => Boolean) => Collection<Element>\r\n\r\n  filter: (Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  <NewElement> map: (transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  <NewElement> map: (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  <NewElement> map: (Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection<Element> {\r\n  filter: (Element => Boolean) => Collection<Element>\r\n\r\n  filter: (Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  map<NewElement>: (transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  map<NewElement>: (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  map<NewElement>: (Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n\r\n#### multiline with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform<Input, Output>:\r\n  Input => Output\r\n\r\nTransform<Input, Output>:\r\n  (Input) => Output\r\n\r\nTransform<Input, Output>:\r\n  (Input => Output)\r\n\r\nFilter<Element>:\r\n  (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter<Element>:\r\n  (Transform<Element, Boolean>, Element[]) => Element[]\r\n\r\nMap<Input, Output>:\r\n  (Input => Output, Input[]) => Output[]\r\n\r\nMap<Input, Output>:\r\n  (Transform<Input, Output>, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection<Element> {\r\n  filter:\r\n    (Element => Boolean) => Collection<Element>\r\n\r\n  filter:\r\n    (Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  <NewElement> map:\r\n    (transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  <NewElement> map:\r\n    (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  <NewElement> map:\r\n    (Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection<Element> {\r\n  filter:\r\n    (Element => Boolean) => Collection<Element>\r\n\r\n  filter:\r\n    (Transform<Element, Boolean>) => Collection<Element>\r\n\r\n  map<NewElement>:\r\n    (transform: Element => NewElement) => Collection<NewElement>\r\n  \r\n  map<NewElement>:\r\n    (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n\r\n  map<NewElement>:\r\n    (Transform<Element, NewElement>) => Collection<NewElement>\r\n}\r\n```\r\n\r\n#### multiline with curly brackets\r\n\r\n##### Functions\r\n\r\n```\r\nTransform<Input, Output> {\r\n  Input => Output\r\n}\r\n\r\nTransform<Input, Output> {\r\n  (Input) => Output\r\n}\r\n\r\nTransform<Input, Output> {\r\n  (Input => Output)\r\n}\r\n\r\nFilter<Element> {\r\n  (Element => Boolean, Element[]) => Element[]\r\n}\r\n\r\nFilter<Element> {\r\n  (Transform<Element, Boolean>, Element[]) => Element[]\r\n}\r\n\r\nMap<Input, Output> {\r\n  (Input => Output, Input[]) => Output[]\r\n}\r\n\r\nMap<Input, Output> {\r\n  (Transform<Input, Output>, Input[]) => Output[]\r\n}\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection<Element> {\r\n  filter {\r\n    (Element => Boolean) => Collection<Element>\r\n  }\r\n\r\n  filter {\r\n    (Transform<Element, Boolean>) => Collection<Element>\r\n  }\r\n\r\n  <NewElement> map {\r\n    (transform: Element => NewElement) => Collection<NewElement>\r\n  }\r\n  \r\n  <NewElement> map {\r\n    (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n  }\r\n\r\n  <NewElement> map {\r\n    (Transform<Element, NewElement>) => Collection<NewElement>\r\n  }\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection<Element> {\r\n  filter {\r\n    (Element => Boolean) => Collection<Element>\r\n  }\r\n\r\n  filter {\r\n    (Transform<Element, Boolean>) => Collection<Element>\r\n  }\r\n\r\n  map<NewElement> {\r\n    (transform: Element => NewElement) => Collection<NewElement>\r\n  }\r\n  \r\n  map<NewElement> {\r\n    (transform: Transform<Element, NewElement>) => Collection<NewElement>\r\n  }\r\n\r\n  map<NewElement> {\r\n    (Transform<Element, NewElement>) => Collection<NewElement>\r\n  }\r\n}\r\n```\r\n\r\n### Square Brackets Syntax\r\nType arguments are enclosed in square brackets and are separated by commas. This syntax is influenced by Scala.\r\n\r\n\r\n#### single-line without colons\r\n\r\n##### Functions\r\n```\r\nTransform[Input, Output] Input => Output\r\n\r\nTransform[Input, Output] (Input) => Output\r\n\r\nTransform[Input, Output] (Input => Output)\r\n\r\nFilter[Element] (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter[Element] (Transform[Element, Boolean], Element[]) => Element[]\r\n\r\nMap[Input, Output] (Input => Output, Input[]) => Output[]\r\n\r\nMap[Input, Output] (Transform[Input, Output], Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection[Element] {\r\n  filter(Element => Boolean) => Collection[Element]\r\n\r\n  filter(Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  [NewElement] map(transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  [NewElement] map(transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  [NewElement] map(Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection[Element] {\r\n  filter(Element => Boolean) => Collection[Element]\r\n\r\n  filter(Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  map[NewElement](transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  map[NewElement](transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  map[NewElement](Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n\r\n#### single-line with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform[Input, Output]: Input => Output\r\n\r\nTransform[Input, Output]: (Input) => Output\r\n\r\nTransform[Input, Output]: (Input => Output)\r\n\r\nFilter[Element]: (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter[Element]: (Transform[Element, Boolean], Element[]) => Element[]\r\n\r\nMap[Input, Output]: (Input => Output, Input[]) => Output[]\r\n\r\nMap[Input, Output]: (Transform[Input, Output], Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection[Element] {\r\n  filter: (Element => Boolean) => Collection[Element]\r\n\r\n  filter: (Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  [NewElement] map: (transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  [NewElement] map: (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  [NewElement] map: (Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection[Element] {\r\n  filter: (Element => Boolean) => Collection[Element]\r\n\r\n  filter: (Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  map[NewElement]: (transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  map[NewElement]: (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  map[NewElement]: (Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n\r\n#### multiline with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform[Input, Output]:\r\n  Input => Output\r\n\r\nTransform[Input, Output]:\r\n  (Input) => Output\r\n\r\nTransform[Input, Output]:\r\n  (Input => Output)\r\n\r\nFilter[Element]:\r\n  (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter[Element]:\r\n  (Transform[Element, Boolean], Element[]) => Element[]\r\n\r\nMap[Input, Output]:\r\n  (Input => Output, Input[]) => Output[]\r\n\r\nMap[Input, Output]:\r\n  (Transform[Input, Output], Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection[Element] {\r\n  filter:\r\n    (Element => Boolean) => Collection[Element]\r\n\r\n  filter:\r\n    (Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  [NewElement] map:\r\n    (transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  [NewElement] map:\r\n    (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  [NewElement] map:\r\n    (Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection[Element] {\r\n  filter:\r\n    (Element => Boolean) => Collection[Element]\r\n\r\n  filter:\r\n    (Transform[Element, Boolean]) => Collection[Element]\r\n\r\n  map[NewElement]:\r\n    (transform: Element => NewElement) => Collection[NewElement]\r\n  \r\n  map[NewElement]:\r\n    (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n\r\n  map[NewElement]:\r\n    (Transform[Element, NewElement]) => Collection[NewElement]\r\n}\r\n```\r\n\r\n#### multiline with curly brackets\r\n\r\n##### Functions\r\n\r\n```\r\nTransform[Input, Output] {\r\n  Input => Output\r\n}\r\n\r\nTransform[Input, Output] {\r\n  (Input) => Output\r\n}\r\n\r\nTransform[Input, Output] {\r\n  (Input => Output)\r\n}\r\n\r\nFilter[Element] {\r\n  (Element => Boolean, Element[]) => Element[]\r\n}\r\n\r\nFilter[Element] {\r\n  (Transform[Element, Boolean], Element[]) => Element[]\r\n}\r\n\r\nMap[Input, Output] {\r\n  (Input => Output, Input[]) => Output[]\r\n}\r\n\r\nMap[Input, Output] {\r\n  (Transform[Input, Output], Input[]) => Output[]\r\n}\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection[Element] {\r\n  filter {\r\n    (Element => Boolean) => Collection[Element]\r\n  }\r\n\r\n  filter {\r\n    (Transform[Element, Boolean]) => Collection[Element]\r\n  }\r\n\r\n  [NewElement] map {\r\n    (transform: Element => NewElement) => Collection[NewElement]\r\n  }\r\n  \r\n  [NewElement] map {\r\n    (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n  }\r\n\r\n  [NewElement] map {\r\n    (Transform[Element, NewElement]) => Collection[NewElement]\r\n  }\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection[Element] {\r\n  filter {\r\n    (Element => Boolean) => Collection[Element]\r\n  }\r\n\r\n  filter {\r\n    (Transform[Element, Boolean]) => Collection[Element]\r\n  }\r\n\r\n  map[NewElement] {\r\n    (transform: Element => NewElement) => Collection[NewElement]\r\n  }\r\n  \r\n  map[NewElement] {\r\n    (transform: Transform[Element, NewElement]) => Collection[NewElement]\r\n  }\r\n\r\n  map[NewElement] {\r\n    (Transform[Element, NewElement]) => Collection[NewElement]\r\n  }\r\n}\r\n```\r\n\r\n\r\n### Parentheses Syntax\r\nType arguments are enclosed in parentheses and are separated by commas. This syntax is influenced by JavaScript function notation. Since a generic type is a type constructor/function that takes types as arguments and returns a concrete type.\r\n\r\n\r\n#### single-line without colons\r\n\r\n##### Functions\r\n```\r\nTransform(Input, Output) Input => Output\r\n\r\nTransform(Input, Output) (Input) => Output\r\n\r\nTransform(Input, Output) (Input => Output)\r\n\r\nFilter(Element) (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter(Element) (Transform(Element, Boolean), Element[]) => Element[]\r\n\r\nMap(Input, Output) (Input => Output, Input[]) => Output[]\r\n\r\nMap(Input, Output) (Transform(Input, Output), Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection(Element) {\r\n  filter(Element => Boolean) => Collection(Element)\r\n\r\n  filter(Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  (NewElement) map(transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  (NewElement) map(transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  (NewElement) map(Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection(Element) {\r\n  filter(Element => Boolean) => Collection(Element)\r\n\r\n  filter(Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  map(NewElement)(transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  map(NewElement)(transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  map(NewElement)(Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n\r\n#### single-line with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform(Input, Output): Input => Output\r\n\r\nTransform(Input, Output): (Input) => Output\r\n\r\nTransform(Input, Output): (Input => Output)\r\n\r\nFilter(Element): (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter(Element): (Transform(Element, Boolean), Element[]) => Element[]\r\n\r\nMap(Input, Output): (Input => Output, Input[]) => Output[]\r\n\r\nMap(Input, Output): (Transform(Input, Output), Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection(Element) {\r\n  filter: (Element => Boolean) => Collection(Element)\r\n\r\n  filter: (Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  (NewElement) map: (transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  (NewElement) map: (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  (NewElement) map: (Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection(Element) {\r\n  filter: (Element => Boolean) => Collection(Element)\r\n\r\n  filter: (Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  map(NewElement): (transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  map(NewElement): (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  map(NewElement): (Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n\r\n#### multiline with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform(Input, Output):\r\n  Input => Output\r\n\r\nTransform(Input, Output):\r\n  (Input) => Output\r\n\r\nTransform(Input, Output):\r\n  (Input => Output)\r\n\r\nFilter(Element):\r\n  (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter(Element):\r\n  (Transform(Element, Boolean), Element[]) => Element[]\r\n\r\nMap(Input, Output):\r\n  (Input => Output, Input[]) => Output[]\r\n\r\nMap(Input, Output):\r\n  (Transform(Input, Output), Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection(Element) {\r\n  filter:\r\n    (Element => Boolean) => Collection(Element)\r\n\r\n  filter:\r\n    (Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  (NewElement) map:\r\n    (transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  (NewElement) map:\r\n    (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  (NewElement) map:\r\n    (Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection(Element) {\r\n  filter:\r\n    (Element => Boolean) => Collection(Element)\r\n\r\n  filter:\r\n    (Transform(Element, Boolean)) => Collection(Element)\r\n\r\n  map(NewElement):\r\n    (transform: Element => NewElement) => Collection(NewElement)\r\n  \r\n  map(NewElement):\r\n    (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n\r\n  map(NewElement):\r\n    (Transform(Element, NewElement)) => Collection(NewElement)\r\n}\r\n```\r\n\r\n#### multiline with curly brackets\r\n\r\n##### Functions\r\n\r\n```\r\nTransform(Input, Output) {\r\n  Input => Output\r\n}\r\n\r\nTransform(Input, Output) {\r\n  (Input) => Output\r\n}\r\n\r\nTransform(Input, Output) {\r\n  (Input => Output)\r\n}\r\n\r\nFilter(Element) {\r\n  (Element => Boolean, Element[]) => Element[]\r\n}\r\n\r\nFilter(Element) {\r\n  (Transform(Element, Boolean), Element[]) => Element[]\r\n}\r\n\r\nMap(Input, Output) {\r\n  (Input => Output, Input[]) => Output[]\r\n}\r\n\r\nMap(Input, Output) {\r\n  (Transform(Input, Output), Input[]) => Output[]\r\n}\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection(Element) {\r\n  filter {\r\n    (Element => Boolean) => Collection(Element)\r\n  }\r\n\r\n  filter {\r\n    (Transform(Element, Boolean)) => Collection(Element)\r\n  }\r\n\r\n  (NewElement) map {\r\n    (transform: Element => NewElement) => Collection(NewElement)\r\n  }\r\n  \r\n  (NewElement) map {\r\n    (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n  }\r\n\r\n  (NewElement) map {\r\n    (Transform(Element, NewElement)) => Collection(NewElement)\r\n  }\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection(Element) {\r\n  filter {\r\n    (Element => Boolean) => Collection(Element)\r\n  }\r\n\r\n  filter {\r\n    (Transform(Element, Boolean)) => Collection(Element)\r\n  }\r\n\r\n  map(NewElement) {\r\n    (transform: Element => NewElement) => Collection(NewElement)\r\n  }\r\n  \r\n  map(NewElement) {\r\n    (transform: Transform(Element, NewElement)) => Collection(NewElement)\r\n  }\r\n\r\n  map(NewElement) {\r\n    (Transform(Element, NewElement)) => Collection(NewElement)\r\n  }\r\n}\r\n```\r\n\r\n\r\n### Whitespace Syntax\r\nType arguments are written without backets and are separated by whitespace. This syntax is [influenced by Elm and Haskell](https://github.com/ericelliott/rtype/issues/55#issuecomment-173989053).\r\n\r\n#### single-line without colons\r\n\r\n##### Functions\r\n```\r\nTransform Input Output Input => Output\r\n\r\nTransform Input Output (Input) => Output\r\n\r\nTransform Input Output (Input => Output)\r\n\r\nFilter Element (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter Element (Transform Element Boolean, Element[]) => Element[]\r\n\r\nMap Input Output (Input => Output, Input[]) => Output[]\r\n\r\nMap Input Output (Transform Input Output, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection Element {\r\n  filter(Element => Boolean) => Collection Element\r\n\r\n  filter(Transform Element Boolean) => Collection Element\r\n\r\n   NewElement map(transform: Element => NewElement) => Collection NewElement\r\n  \r\n   NewElement map(transform: Transform Element NewElement) => Collection NewElement\r\n\r\n   NewElement map(Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection Element {\r\n  filter(Element => Boolean) => Collection Element\r\n\r\n  filter(Transform Element Boolean) => Collection Element\r\n\r\n  map NewElement(transform: Element => NewElement) => Collection NewElement\r\n  \r\n  map NewElement(transform: Transform Element NewElement) => Collection NewElement\r\n\r\n  map NewElement(Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n\r\n#### single-line with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform Input Output: Input => Output\r\n\r\nTransform Input Output: (Input) => Output\r\n\r\nTransform Input Output: (Input => Output)\r\n\r\nFilter Element: (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter Element: (Transform Element Boolean, Element[]) => Element[]\r\n\r\nMap Input Output: (Input => Output, Input[]) => Output[]\r\n\r\nMap Input Output: (Transform Input Output, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection Element {\r\n  filter: (Element => Boolean) => Collection Element\r\n\r\n  filter: (Transform Element Boolean) => Collection Element\r\n\r\n   NewElement map: (transform: Element => NewElement) => Collection NewElement\r\n  \r\n   NewElement map: (transform: Transform Element NewElement) => Collection NewElement\r\n\r\n   NewElement map: (Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection Element {\r\n  filter: (Element => Boolean) => Collection Element\r\n\r\n  filter: (Transform Element Boolean) => Collection Element\r\n\r\n  map NewElement: (transform: Element => NewElement) => Collection NewElement\r\n  \r\n  map NewElement: (transform: Transform Element NewElement) => Collection NewElement\r\n\r\n  map NewElement: (Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n\r\n#### multiline with colons\r\n\r\n##### Functions\r\n\r\n```\r\nTransform Input Output:\r\n  Input => Output\r\n\r\nTransform Input Output:\r\n  (Input) => Output\r\n\r\nTransform Input Output:\r\n  (Input => Output)\r\n\r\nFilter Element:\r\n  (Element => Boolean, Element[]) => Element[]\r\n\r\nFilter Element:\r\n  (Transform Element Boolean, Element[]) => Element[]\r\n\r\nMap Input Output:\r\n  (Input => Output, Input[]) => Output[]\r\n\r\nMap Input Output:\r\n  (Transform Input Output, Input[]) => Output[]\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection Element {\r\n  filter:\r\n    (Element => Boolean) => Collection Element\r\n\r\n  filter:\r\n    (Transform Element Boolean) => Collection Element\r\n\r\n   NewElement map:\r\n    (transform: Element => NewElement) => Collection NewElement\r\n  \r\n   NewElement map:\r\n    (transform: Transform Element NewElement) => Collection NewElement\r\n\r\n   NewElement map:\r\n    (Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection Element {\r\n  filter:\r\n    (Element => Boolean) => Collection Element\r\n\r\n  filter:\r\n    (Transform Element Boolean) => Collection Element\r\n\r\n  map NewElement:\r\n    (transform: Element => NewElement) => Collection NewElement\r\n  \r\n  map NewElement:\r\n    (transform: Transform Element NewElement) => Collection NewElement\r\n\r\n  map NewElement:\r\n    (Transform Element NewElement) => Collection NewElement\r\n}\r\n```\r\n\r\n#### multiline with curly brackets\r\n\r\n##### Functions\r\n\r\n```\r\nTransform Input Output {\r\n  Input => Output\r\n}\r\n\r\nTransform Input Output {\r\n  (Input) => Output\r\n}\r\n\r\nTransform Input Output {\r\n  (Input => Output)\r\n}\r\n\r\nFilter Element {\r\n  (Element => Boolean, Element[]) => Element[]\r\n}\r\n\r\nFilter Element {\r\n  (Transform Element Boolean, Element[]) => Element[]\r\n}\r\n\r\nMap Input Output {\r\n  (Input => Output, Input[]) => Output[]\r\n}\r\n\r\nMap Input Output {\r\n  (Transform Input Output, Input[]) => Output[]\r\n}\r\n```\r\n\r\n##### Interface\r\n\r\n###### Generic type arguments of methods before method name\r\n ```\r\ninterface Collection Element {\r\n  filter {\r\n    (Element => Boolean) => Collection Element\r\n  }\r\n\r\n  filter {\r\n    (Transform Element Boolean) => Collection Element\r\n  }\r\n\r\n   NewElement map {\r\n    (transform: Element => NewElement) => Collection NewElement\r\n  }\r\n  \r\n   NewElement map {\r\n    (transform: Transform Element NewElement) => Collection NewElement\r\n  }\r\n\r\n   NewElement map {\r\n    (Transform Element NewElement) => Collection NewElement\r\n  }\r\n}\r\n```\r\n\r\n###### Generic type arguments of methods after method name\r\n```\r\ninterface Collection Element {\r\n  filter {\r\n    (Element => Boolean) => Collection Element\r\n  }\r\n\r\n  filter {\r\n    (Transform Element Boolean) => Collection Element\r\n  }\r\n\r\n  map NewElement {\r\n    (transform: Element => NewElement) => Collection NewElement\r\n  }\r\n  \r\n  map NewElement {\r\n    (transform: Transform Element NewElement) => Collection NewElement\r\n  }\r\n\r\n  map NewElement {\r\n    (Transform Element NewElement) => Collection NewElement\r\n  }\r\n}\r\n```\r\n\r\n## Comparison of syntax proposals\r\n\r\nIt is hard to compare syntax impersonal and objectively. Opinions might differ on readability and the question if familiarity of a syntax is an advantage or an disadvantage. Thus, I mainly collect opinions as quotations. I will add opinions that arise in further discussion. Please tell me if any opinion or aspect is missing or if something is not quite appropriate.\r\n\r\n\r\n### Angle Brackets Syntax\r\n\r\nSimilar to C++ templates and Java, C# and TypeScript generics.\r\n\r\n> Thousands of C++/Java/C# developers are currently being converted to JS developers, you all know that. Students in (high)schools study the C++/Java/C#. I would recommend to make sure these people can read rtype easily without browsing the documentation (JSDoc is quite readable, btw, thus popular).\r\n> [...]\r\n> TypeScript syntax is readable to most developers\r\n> -- [koresar](https://github.com/ericelliott/rtype/issues/55#issuecomment-174105983)\r\n\r\n<!-- -->\r\n> The problem is that the <> syntax isn't consistent between languages anyway.\r\n> Look at Java, C#, Kotlin, Rust, etc. all of them are doing it differently.\r\n> -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/cwto6b5)\r\n\r\n<!-- -->\r\n> TypeScript's generics in function signatures, and the TypeScript syntax feels like an assault on my senses\r\n> -- [ericelliott](https://github.com/ericelliott/rtype/issues/55#issuecomment-171828272)\r\n\r\n<!-- -->\r\n> I think there's something about the angle brackets that drives me crazy. Reminds me of C++ templates or something (which I have bad memories of).\r\n> -- [ericelliott](https://github.com/ericelliott/rtype/issues/55#issuecomment-171909162)\r\n\r\n<!-- -->\r\n> :-1: For angle brackets\r\n> -- [BerkeleyTrue](https://github.com/ericelliott/rtype/issues/55#issuecomment-171918980)\r\n\r\n<!-- -->\r\n> Java's approach is saying \"f*ck it\", let's just have stuff like `method<String>()`, but `instance.<String>method()` at use-site; and at declaration-site (different issue) it's even more different with `class Box<T>` vs. `<T> void foo(T t)`.\r\n> -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/)\r\n\r\n\r\n#### Advantages\r\n\r\n- common syntax in many languages\r\n\r\n\r\n#### Disadvatages\r\n\r\n- < ([Unicode Character 'LESS-THAN SIGN'](http://www.fileformat.info/info/unicode/char/3c/index.htm)) and > ([Unicode Character 'GREATER-THAN SIGN'](http://www.fileformat.info/info/unicode/char/003e/index.htm)) used as brackets are **harder to read**, since they are no real brackets. The real angle brackets are &#12296; ([Unicode Character 'LEFT ANGLE BRACKET'](http://www.fileformat.info/info/unicode/char/3008/index.htm)) and &#12297; ([Unicode Character 'RIGHT ANGLE BRACKET'](http://www.fileformat.info/info/unicode/char/3009/index.htm)).\r\n\r\n- parsing issues\r\n  > Using `<>` for generics is a historical accident. If you look at all the languages which adopted it, all of them need horrible hacks to work around the intrinsic issues.\r\n  > -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/cwt3vsq)\r\n\r\n  <!-- -->\r\n  > > Do you have any examples where they had to work around these parsing issues due to using <> for generics?\r\n  >\r\n  > C# and Kotlin for example just keep reading after the `<` and have a huge list of tokens to determine whether it's a comparison, Generics, or if they need to keep reading further. They basically need unlimited lookahead, and if they figure it out, they rollback the parser state and parse it again, with more information.\r\n  > -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/cwt6faw)\r\n\r\n  <!-- -->\r\n  > > In return you avoid the compiler having to look ahead a little during parsing. Is that really a good trade? I don't.\r\n  > \r\n  > If even the parser has trouble reading, people will very likely also have trouble with comprehending things.\r\n  > -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/cwto6b5)  \r\n\r\n  <!-- -->\r\n  > In case of a single-parameter-function as concrete type argument readability is decreased with angle brackets notation due to the fact that a closing angle bracket is used as arrow head:\r\n  >  ```TS\r\n  >  MyInterface<String => String>   // angle bracket syntax\r\n  >\r\n  >  MyInterface<(String => String)> // angle bracket syntax, IMO parentheses don't increase readability in this case\r\n  >\r\n  >  MyInterface (String => String)  // whitespace syntax (type argument has to be enclosed in parentheses, otherwise it would be equal to `(MyInterface String) => String`\r\n  >\r\n  >  MyInterface(String => String)   // parentheses/function syntax; Note: Could also be written like whitespace syntax in this case: `MyInterface (String => String)`\r\n  >  ```\r\n  > -- [maiermic](https://github.com/ericelliott/rtype/issues/55#issuecomment-175461121)\r\n\r\n  <!-- -->\r\n  > `map<t, u>(fn: (x: t) => u, list: t[]) => u[];`\r\n  > IMO, this is even worse than the C++ & Java versions because of the arrow functions. Note how the closing angle bracket for the type parameter declaration looks visually very similar to the arrows in the arrow functions. My brain tries to match them up.\r\n  > \r\n  > My brain also struggles with the groupings of type parameters and function parameters, mostly lost in the syntax noise.\r\n  > \r\n  > [...]\r\n  > \r\n  > ```TS \r\n  > interface StringStringThing:\r\n  >   MyInterface<String => String>\r\n  > ```\r\n  > Which visually looks a bit like this:\r\n  > ```TS \r\n  > interface StringStringThing:\r\n  >   MyInterface<String => // wtf is the rest of that nonsense?\r\n  > ```\r\n  >\r\n  > -- [ericelliott](https://github.com/ericelliott/rtype/issues/55#issuecomment-176489410)\r\n\r\n\r\n\r\n### Square Brackets Syntax\r\n\r\nSimilar to Scala generics\r\n\r\n> Java's approach is saying \"f*ck it\", let's just have stuff like `method<String>()`, but `instance.<String>method()` at use-site; and at declaration-site (different issue) it's even more different with `class Box<T>` vs. `<T> void foo(T t)`.\r\n> In Scala, everything is regular and consistent. The `[]` are always at the same place, everywhere.\r\n> -- [unknown reddit user](https://www.reddit.com/r/programming/comments/3rzpi7/porting_ceylon_ide_to_intellij/)\r\n\r\n#### Advantages\r\n- consistency: every time you see `[]` (in rtype) a generic type is described\r\n\r\n#### Disadvatages\r\n- every time you see `[]` in JavaScript an object property or array element is accessed.\r\n- conflicts with current rtype array syntax\r\n  - might be resolved by writting `[Number]` instead of `Number[]`\r\n\r\n    > We could write `Array[T]` instead of `T[]` in rtype. We might use `[T]` as short version of `Array[T]`. One benefit of writing the generic type in brackets is better readablity of type expressions:\r\n    > `(Number | String)[]` vs. `[Number | String]` or `Array[Number | String]`\r\n    > -- [maiermic](https://github.com/ericelliott/rtype/issues/55#issuecomment-171919088)\r\n\r\n\r\n### Parentheses Syntax\r\n\r\nSimilar to a regular JavaScript function.\r\n\r\n> **Advantages:**\r\n> \r\n> - it looks similar to a function declaration\r\n> - it behaves similar to a function declaration: defines a type constructor (= function) that takes types as parameters and returns a type\r\n>\r\n> -- [maiermic](https://github.com/ericelliott/rtype/issues/55#issuecomment-174300619)\r\n\r\n<!-- -->\r\n> **Disadvantages:**\r\n> \r\n> - it looks similar to a function declaration\r\n> - it behaves similar to a function declaration: defines a type constructor (= function) that takes types as parameters and returns a type\r\n> \r\n> Sorry for trolling like messages. That's my personal opinion. We should lean towards readability. Using parenthesis for everything damages readability significantly. (One of the reasons to not like Lisp is the parenthesis bloat.)\r\n> -- [koresar](https://github.com/ericelliott/rtype/issues/55#issuecomment-174350060)\r\n\r\n\r\n#### Advantages\r\n- type constructor are functions\r\n\r\n  > Generic types like `Map` are not just *type names*. They are *type constructors*:\r\n  > > type constructor is a feature of a typed formal language that __builds new types from old ones__\r\n  > > [Wikipedia - Type constructor](https://en.wikipedia.org/wiki/Type_constructor)\r\n  > \r\n  > That means a *type constructor* is not a type itself, but it describes a class of types.\r\n  > -- [maiermic](https://github.com/ericelliott/rtype/issues/55#issuecomment-174270840)\r\n\r\n  <!-- -->\r\n  > A *type constructor* is more like a function that returns a type:\r\n  > \r\n  > ```\r\n  > // type constructor Map\r\n  > function Map(t: Type, u: Type): Type {\r\n  >   return ((x: t) => u, list: t[]) => u[]\r\n  > }\r\n  > ```\r\n  > -- [maiermic](https://github.com/ericelliott/rtype/issues/55#issuecomment-174271489)\r\n\r\n#### Disadvatages\r\n- a type constructor might get confused with a regular function\r\n- if types are inferred, type arguments are passed implicitly, which is not possible in regular JavaScript functions\r\n\r\n\r\n### Whitespace Syntax\r\n\r\nSimilar to Elm and Haskell.\r\n\r\n#### Advantages\r\n- fewer characters (no special brackets) are needed\r\n- reusable/composable: due to curring, partial function application of type constructors is possible\r\n\r\n#### Disadvatages\r\n- whitespace syntax introduces currying. Most JavaScript developers are not familiar with this concept of function notation.\r\n\r\n  > Haskell is known but an exotic language yet. For C++/Java/C# developers it is counter intuitive that the space symbol have a special syntactic meaning. Frankly speaking, I still do not understand what's that: `Transform t u: (x: t) => u`.\r\n  > -- [koresar](https://github.com/ericelliott/rtype/issues/55#issuecomment-174105983)\r\n"},"comment":{"url":"https://api.github.com/repos/ericelliott/rtype/issues/comments/216974046","html_url":"https://github.com/ericelliott/rtype/issues/80#issuecomment-216974046","issue_url":"https://api.github.com/repos/ericelliott/rtype/issues/80","id":216974046,"user":{"login":"ericelliott","id":364727,"avatar_url":"https://avatars.githubusercontent.com/u/364727?v=3","gravatar_id":"","url":"https://api.github.com/users/ericelliott","html_url":"https://github.com/ericelliott","followers_url":"https://api.github.com/users/ericelliott/followers","following_url":"https://api.github.com/users/ericelliott/following{/other_user}","gists_url":"https://api.github.com/users/ericelliott/gists{/gist_id}","starred_url":"https://api.github.com/users/ericelliott/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericelliott/subscriptions","organizations_url":"https://api.github.com/users/ericelliott/orgs","repos_url":"https://api.github.com/users/ericelliott/repos","events_url":"https://api.github.com/users/ericelliott/events{/privacy}","received_events_url":"https://api.github.com/users/ericelliott/received_events","type":"User","site_admin":false},"created_at":"2016-05-04T19:26:50Z","updated_at":"2016-05-04T19:26:50Z","body":"OK, let's address the one point you did raise that has some merit. Arrays have automatically number-indexed keys. I think it's clear that when we specify a collection type with square brackets, like `Foo[String]`, we're talking about the type of the *values*, not the type of the keys. 99.9% of the time this is what we want, and that syntax works fine. **Let's make it easy for the 99% case.**\r\n\r\nNow, for the edge case, Objects can have typed *keys.* For example, how do we specify that an object's keys must all be of type `symbol`?\r\n\r\nIMO, for that, we'll need some notation that allows us to address object keys, specifically, in the same way we can address object values with `Foo[Bar]` notation. I think discussion and suggestions for that should probably be considered a separate issue."}}