{"action":"created","issue":{"url":"https://api.github.com/repos/evilsoft/crocks/issues/269","repository_url":"https://api.github.com/repos/evilsoft/crocks","labels_url":"https://api.github.com/repos/evilsoft/crocks/issues/269/labels{/name}","comments_url":"https://api.github.com/repos/evilsoft/crocks/issues/269/comments","events_url":"https://api.github.com/repos/evilsoft/crocks/issues/269/events","html_url":"https://github.com/evilsoft/crocks/issues/269","id":320528392,"node_id":"MDU6SXNzdWUzMjA1MjgzOTI=","number":269,"title":"Add a Tuple Type","user":{"login":"evilsoft","id":3665793,"node_id":"MDQ6VXNlcjM2NjU3OTM=","avatar_url":"https://avatars1.githubusercontent.com/u/3665793?v=4","gravatar_id":"","url":"https://api.github.com/users/evilsoft","html_url":"https://github.com/evilsoft","followers_url":"https://api.github.com/users/evilsoft/followers","following_url":"https://api.github.com/users/evilsoft/following{/other_user}","gists_url":"https://api.github.com/users/evilsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/evilsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/evilsoft/subscriptions","organizations_url":"https://api.github.com/users/evilsoft/orgs","repos_url":"https://api.github.com/users/evilsoft/repos","events_url":"https://api.github.com/users/evilsoft/events{/privacy}","received_events_url":"https://api.github.com/users/evilsoft/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":{"login":"karthikiyengar","id":8260207,"node_id":"MDQ6VXNlcjgyNjAyMDc=","avatar_url":"https://avatars0.githubusercontent.com/u/8260207?v=4","gravatar_id":"","url":"https://api.github.com/users/karthikiyengar","html_url":"https://github.com/karthikiyengar","followers_url":"https://api.github.com/users/karthikiyengar/followers","following_url":"https://api.github.com/users/karthikiyengar/following{/other_user}","gists_url":"https://api.github.com/users/karthikiyengar/gists{/gist_id}","starred_url":"https://api.github.com/users/karthikiyengar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karthikiyengar/subscriptions","organizations_url":"https://api.github.com/users/karthikiyengar/orgs","repos_url":"https://api.github.com/users/karthikiyengar/repos","events_url":"https://api.github.com/users/karthikiyengar/events{/privacy}","received_events_url":"https://api.github.com/users/karthikiyengar/received_events","type":"User","site_admin":false},"assignees":[{"login":"karthikiyengar","id":8260207,"node_id":"MDQ6VXNlcjgyNjAyMDc=","avatar_url":"https://avatars0.githubusercontent.com/u/8260207?v=4","gravatar_id":"","url":"https://api.github.com/users/karthikiyengar","html_url":"https://github.com/karthikiyengar","followers_url":"https://api.github.com/users/karthikiyengar/followers","following_url":"https://api.github.com/users/karthikiyengar/following{/other_user}","gists_url":"https://api.github.com/users/karthikiyengar/gists{/gist_id}","starred_url":"https://api.github.com/users/karthikiyengar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karthikiyengar/subscriptions","organizations_url":"https://api.github.com/users/karthikiyengar/orgs","repos_url":"https://api.github.com/users/karthikiyengar/repos","events_url":"https://api.github.com/users/karthikiyengar/events{/privacy}","received_events_url":"https://api.github.com/users/karthikiyengar/received_events","type":"User","site_admin":false}],"milestone":null,"comments":13,"created_at":"2018-05-05T17:49:33Z","updated_at":"2018-07-25T05:17:00Z","closed_at":"2018-07-25T05:17:00Z","author_association":"OWNER","body":"A simple Tuple type that lets us define a tuple of any size would be amazing.\r\nTo get a constructor, the size of the tuple will need to be specified to get back an instance constructor, fixed to the size specified:\r\n\r\n```js\r\nconst Triple = Tuple(3)\r\n\r\n// t :: Tuple String Boolean Number\r\nconst t = Triple('a', true, 97)\r\n```\r\n*Implementation detail*: When providing the constructor, we should return (up to Tuple-10) an anonymous function with the length of the function matching the size of the tuple. Providing the proper length for the function allows us to integrate with other libs curry and partial application helpers.\r\n\r\n```js\r\n// suggested/possible implementation\r\n\r\nfunction _Tuple(n) {\r\n  if(!(isInteger(n) || n > 1)) {\r\n    throw\r\n  }\r\n  const _type = () =>\r\n     `${n}-Tuple`\r\n\r\n  // instance impl\r\n  function Tuple(n, ...parts) {\r\n    if(parts.length !== n) {\r\n       throw\r\n    }\r\n\r\n    // method defs\r\n  \r\n    return {\r\n        inspect, toString: inspect, type: _type, concat, map,\r\n        mapTuple, toArray, project, constructor: Tuple, merge\r\n    }\r\n  }\r\n\r\n  Tuple['@@implements'] = () =>\r\n    [ 'concat', 'map' ]\r\n\r\n  Tuple.type = _type\r\n\r\n  Tuple['@@type'] =\r\n    `crocks/${n}-Tuple`\r\n \r\n  switch(n) {\r\n    case 1: return function(a) { return Tuple(n, a) }\r\n    case 2: return function(a, b) { return Tuple(n, a, b) }\r\n    case 3: return function(a, b, c) { return Tuple(n, a) }\r\n    case 4: return function(a, b, c, d) { return Tuple(n, a, b, c, d) }\r\n    case 5: return function(a, b, c, d, e) { return Tuple(n, a, b, c, d, e) }\r\n    case 6: return function(a, b, c, d, e, f) { return Tuple(n, a, b, c, d, e, f) }\r\n    case 7: return function(a, b, c, d, e, f, g) { return Tuple(n, a, b, c, d, e, f, g) }\r\n    case 8: return function(a, b, c, d, e, f, g, h) { return Tuple(n, a, b, c, d, e, f, g, h) }\r\n    case 9: return function(a, b, c, d, e, f, g, h, i) { return Tuple(n, a, b, c, d, e, f, g, h, i) }\r\n    case 10: return function(a, b, c, d, e, f, g, h, i, j) { return Tuple(n, a, b, c, d, e, f, g, h, i, j) }\r\n  }\r\n\r\n  return function (...parts) { return _Tuple(n, ...parts) }\r\n}\r\n```\r\n\r\n### Instance Methods\r\n* `concat`: when all parts are a semi-group concat them together, if not throw\r\n* `map`: maps the rightmost part with provided function, throw if no function provided\r\n* `mapTuple`: takes one function per number of part, maps each part using the function provided for each. (basically `bimap` for tuples of n-size) Throws if the number of functions provided do not match the size of the tuple.\r\n* `toArray`: provides an array with n elements where n is the number of parts of the Tuple\r\n* `project`: takes a positive integer n <= the size of the tuple and provides the value at that one based position, eg `1 = pair.fst() = pair.toArray[0]`. throws if not an Integer `1-n` where n is the total number of parts for a given Tuple. (this provides the need projections `{π1, π2,...πn}` that make a Product Type a Product Type)\r\n* `merge`: basically exactly what `pair.merge` does.\r\n\r\n### Fantasy-land\r\n* `fantasy-land\\concat`\r\n* `fantasy-land\\map`\r\n\r\n### Pointfree functions\r\n* `mapTuple`\r\n* `project`\r\n* `merge`: This will need to be moved out of `Pair` and into the general pointfree functions (Breaking change"},"comment":{"url":"https://api.github.com/repos/evilsoft/crocks/issues/comments/407635989","html_url":"https://github.com/evilsoft/crocks/issues/269#issuecomment-407635989","issue_url":"https://api.github.com/repos/evilsoft/crocks/issues/269","id":407635989,"node_id":"MDEyOklzc3VlQ29tbWVudDQwNzYzNTk4OQ==","user":{"login":"evilsoft","id":3665793,"node_id":"MDQ6VXNlcjM2NjU3OTM=","avatar_url":"https://avatars1.githubusercontent.com/u/3665793?v=4","gravatar_id":"","url":"https://api.github.com/users/evilsoft","html_url":"https://github.com/evilsoft","followers_url":"https://api.github.com/users/evilsoft/followers","following_url":"https://api.github.com/users/evilsoft/following{/other_user}","gists_url":"https://api.github.com/users/evilsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/evilsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/evilsoft/subscriptions","organizations_url":"https://api.github.com/users/evilsoft/orgs","repos_url":"https://api.github.com/users/evilsoft/repos","events_url":"https://api.github.com/users/evilsoft/events{/privacy}","received_events_url":"https://api.github.com/users/evilsoft/received_events","type":"User","site_admin":false},"created_at":"2018-07-25T05:17:00Z","updated_at":"2018-07-25T05:17:00Z","author_association":"OWNER","body":"Shipped with 0.10.0.\r\nClosing"}}
{"actor":{"display_login":"evilsoft"}}