{"action":"created","issue":{"url":"https://api.github.com/repos/rpominov/static-land/issues/31","repository_url":"https://api.github.com/repos/rpominov/static-land","labels_url":"https://api.github.com/repos/rpominov/static-land/issues/31/labels{/name}","comments_url":"https://api.github.com/repos/rpominov/static-land/issues/31/comments","events_url":"https://api.github.com/repos/rpominov/static-land/issues/31/events","html_url":"https://github.com/rpominov/static-land/pull/31","id":184650741,"number":31,"title":"Improve type signatures","user":{"login":"rpominov","id":825702,"avatar_url":"https://avatars.githubusercontent.com/u/825702?v=3","gravatar_id":"","url":"https://api.github.com/users/rpominov","html_url":"https://github.com/rpominov","followers_url":"https://api.github.com/users/rpominov/followers","following_url":"https://api.github.com/users/rpominov/following{/other_user}","gists_url":"https://api.github.com/users/rpominov/gists{/gist_id}","starred_url":"https://api.github.com/users/rpominov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rpominov/subscriptions","organizations_url":"https://api.github.com/users/rpominov/orgs","repos_url":"https://api.github.com/users/rpominov/repos","events_url":"https://api.github.com/users/rpominov/events{/privacy}","received_events_url":"https://api.github.com/users/rpominov/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2016-10-22T19:56:09Z","updated_at":"2016-10-23T11:43:55Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/rpominov/static-land/pulls/31","html_url":"https://github.com/rpominov/static-land/pull/31","diff_url":"https://github.com/rpominov/static-land/pull/31.diff","patch_url":"https://github.com/rpominov/static-land/pull/31.patch"},"body":"Based on discussion in #30 \r\n\r\nAny feedback appreciated :)"},"comment":{"url":"https://api.github.com/repos/rpominov/static-land/issues/comments/255584001","html_url":"https://github.com/rpominov/static-land/pull/31#issuecomment-255584001","issue_url":"https://api.github.com/repos/rpominov/static-land/issues/31","id":255584001,"user":{"login":"gcanti","id":878912,"avatar_url":"https://avatars.githubusercontent.com/u/878912?v=3","gravatar_id":"","url":"https://api.github.com/users/gcanti","html_url":"https://github.com/gcanti","followers_url":"https://api.github.com/users/gcanti/followers","following_url":"https://api.github.com/users/gcanti/following{/other_user}","gists_url":"https://api.github.com/users/gcanti/gists{/gist_id}","starred_url":"https://api.github.com/users/gcanti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gcanti/subscriptions","organizations_url":"https://api.github.com/users/gcanti/orgs","repos_url":"https://api.github.com/users/gcanti/repos","events_url":"https://api.github.com/users/gcanti/events{/privacy}","received_events_url":"https://api.github.com/users/gcanti/received_events","type":"User","site_admin":false},"created_at":"2016-10-23T11:43:55Z","updated_at":"2016-10-23T11:43:55Z","body":"@rpominov I see. Let me explain my point of view though, I hope can be helpful to the discussion. The following signature \r\n\r\n```\r\nmap :: Functor f => (a → b, f a) → f b\r\n```\r\n\r\nis not ambiguous because when we write `f a` we are just representing a data structure parametrised by one type parameter, kind `* -> *`, (for example `Maybe<A>` or `List<A>` or `Promise<A>`) not a functor. \r\n\r\nFrom a math point of view a functor `F` is a **pair** \r\n\r\n```\r\nF = (mapObject, listMorhism)\r\n```\r\n\r\nwhere the first component acts on objects and the second component acts on morphisms. In our case, let's say the category `JS`, objects are JavaScript types, morphisms are functions and the composition operation of the category is the usual function composition. Hence if we say `Array<A> is a functor`, strictly speaking, is not correct. When we talk about a functor we must always say how we map objects (types) and how we map morphisms (functions). \r\n\r\nThe second component of a functor (\"lift\") has the following signature\r\n\r\n```js\r\nlift :: (a → b) → (fa → fb) // <= maps functions to functions\r\n```\r\n\r\nbut is commonly implemented as the equivalent\r\n\r\n```js\r\nmap :: (a → b, fa) → fb\r\n```\r\n\r\nSome examples\r\n\r\n1) The functor `List = (Array<A>, mapList)`\r\n\r\nwhere\r\n\r\n- (objects) `Array<A>` maps a type `A` to the type `Array<A>`, i.e the array of elements of type `A`\r\n- (morphisms) `mapList = (f, fa) => fa.map(f)`\r\n\r\n2) The functor `Maybe = (?A, mapMaybe)`\r\n\r\nwhere\r\n\r\n- (objects) `?A` maps the `A` to the type `A | null`\r\n- (morphisms) `mapMaybe = (f, fa) => fa === null ? null : f(fa)`\r\n\r\n3) The functor `Promise = (Promise<A>, mapPromise)`\r\n\r\nwhere\r\n\r\n- (objects) `Promise<A>` maps a type `A` to the type `Promise<A>`\r\n- (morphisms) `mapPromise = (f, fa) => fa.then(a => f(a))`\r\n\r\nWe can't say `Array<A>` is a functor, we should say **List is a functor**.\r\n\r\nComing back to our signature\r\n\r\n```\r\nmap :: Functor f => (a → b, f a) → f b\r\n```\r\n\r\n`map` and `f` here are tied together because the functor is the pair `(f a, map)`, not `f a` alone. Hence writing\r\n\r\n```\r\nList.map(f, Maybe.of(x))\r\n```\r\n\r\ndoesn't make sense, because you can't mix the `map` part of a functor (`List`) with the data structure part of another functor (`Maybe`).\r\n"}}
{"actor":{"display_login":"gcanti"}}