{"action":"created","issue":{"url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/88","labels_url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/88/labels{/name}","comments_url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/88/comments","events_url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/88/events","html_url":"https://github.com/fantasyland/fantasy-land/issues/88","id":57274628,"number":88,"title":"Why can `of` be defined on the constructor?","user":{"login":"CrossEye","id":151263,"avatar_url":"https://avatars.githubusercontent.com/u/151263?v=3","gravatar_id":"","url":"https://api.github.com/users/CrossEye","html_url":"https://github.com/CrossEye","followers_url":"https://api.github.com/users/CrossEye/followers","following_url":"https://api.github.com/users/CrossEye/following{/other_user}","gists_url":"https://api.github.com/users/CrossEye/gists{/gist_id}","starred_url":"https://api.github.com/users/CrossEye/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CrossEye/subscriptions","organizations_url":"https://api.github.com/users/CrossEye/orgs","repos_url":"https://api.github.com/users/CrossEye/repos","events_url":"https://api.github.com/users/CrossEye/events{/privacy}","received_events_url":"https://api.github.com/users/CrossEye/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":45,"created_at":"2015-02-11T04:11:10Z","updated_at":"2015-02-16T18:38:18Z","closed_at":null,"body":"It's quite possible that I'm simply missing something simple, but I'm disturbed by this sentence (emphasis added):\r\n\r\n> A value which has an Applicative must provide an `of` method on itself **or** its `constructor` object.\r\n\r\n(All the same points will apply to Monoid's `empty` method, but it's Applicatives which are worrying me now.)\r\n\r\nFor a specification which is usually so prescriptive, this is surprisingly lax.  But that's not the real problem.  It seems to me that this makes it tremendously more difficult to write code that works across all Applicative Types; in fact, it probably makes it impossible.\r\n\r\nA few points:\r\n\r\n  * First of all, the Applicative laws, and Monad's _left identity_ are written only in terms of the instance version of `of`.  Should the specification be taken to read, for instance, \"The appropriate one of `m.of(a).chain(f)` or `m.constructor.of(a).chain(f)` is equivalent to `f(a)` (left identity)\" or some more precise version of the same?\r\n\r\n  * It makes unwarranted assumptions about how I create types.  In these days of `Object.create`, why should the specification assume that I use constructor functions to define my types?  It's quite possible to do without them, and it's growing ever more popular to work that way.\r\n\r\n  * It is possibly incoherent.  Since nothing specifies _which_ of the two I must implement, I can choose to implement the same `of` on both.  This would probably not cause an issue.  But nothing in the specification would prevent me from creating a conforming `of` on the instances and an unrelated `of` on the constructor or vice versa:\r\n\r\n```javascript\r\n    Maybe.of = function(val) {return new Just(val);};\r\n    Maybe.prototype.of = function(val) {throw \"Unknown Preposition\";};\r\n```\r\n\r\nDoes that conform to the specification as written so long as `Maybe.of` upholds the required laws?\r\n\r\nDoes this one so long as `Maybe.prototype.of` upholds the laws?:\r\n\r\n```javascript\r\n    Maybe.of = function(val) {throw \"Unknown Preposition\";};\r\n    Maybe.prototype.of = function(val) {return new Just(val);};\r\n```\r\n\r\nIf so, can anyone suggest a way that I can generically apply `of` to algebraic types without knowing for each specific type which version is being used?\r\n\r\nOr... am I just missing something simple again? \r\n\r\nThis was all brought to mind by a [recent Ramda issue][ri].\r\n\r\n\r\n  [ri]: https://github.com/ramda/ramda/pull/784\r\n"},"comment":{"url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/comments/74553726","html_url":"https://github.com/fantasyland/fantasy-land/issues/88#issuecomment-74553726","issue_url":"https://api.github.com/repos/fantasyland/fantasy-land/issues/88","id":74553726,"user":{"login":"CrossEye","id":151263,"avatar_url":"https://avatars.githubusercontent.com/u/151263?v=3","gravatar_id":"","url":"https://api.github.com/users/CrossEye","html_url":"https://github.com/CrossEye","followers_url":"https://api.github.com/users/CrossEye/followers","following_url":"https://api.github.com/users/CrossEye/following{/other_user}","gists_url":"https://api.github.com/users/CrossEye/gists{/gist_id}","starred_url":"https://api.github.com/users/CrossEye/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CrossEye/subscriptions","organizations_url":"https://api.github.com/users/CrossEye/orgs","repos_url":"https://api.github.com/users/CrossEye/repos","events_url":"https://api.github.com/users/CrossEye/events{/privacy}","received_events_url":"https://api.github.com/users/CrossEye/received_events","type":"User","site_admin":false},"created_at":"2015-02-16T18:38:17Z","updated_at":"2015-02-16T18:38:17Z","body":"Ok, I think I'm coming to terms with at least one reason why this is bothering me from a mathematical point of view.  As far as I can tell, the FantasyLand laws allow for the empty set to be treated as a Monoid!  \r\n\r\nThis is of course a problem for something like `foldMap`, which is expected to return an actual value of the Monoid in question.\r\n\r\nA normal mathematical definition of a Monoid, and similarly the one from Haskell has to do with a set having an associative binary operation and an identity element.  The operation (actually in Semigroup is) no issue.  But `empty` is a real problem.  \r\n\r\nDefinitions from other fields, which actually insist on an identity element don't have this issue.  But FantasyLand tries to derive everything from values, or at least to allow you to define your Monoid in that manner.\r\n\r\nHere's my reasoning:\r\n\r\nMy type = E = {};  All these hold trivially since E is empty:\r\n\r\n  * ∀a ∈ E,  `a.equals(a) === true`\r\n  * ∀a, b ∈ E, `a.equals(b) === b.equals(a)`\r\n  * ∀a, b, c ∈ E, `If a.equals(b) and b.equals(c), then a.equals(c)`\r\n\r\nHence E is a Setoid.  No surprise.\r\n\r\nAnd E is a Semigroup, again trivially since E is Empty:\r\n\r\n  * ∀a, b, c ∈ E, `a.concat(b).concat(c) is equivalent to a.concat(b.concat(c))`\r\n\r\nBut now I have a choice.  I can choose to say that this type's `empty` is defined on my instances, as the spec allows.  Then these become trivially true, again since E is empty:\r\n\r\n  * ∀m ∈ E, `m.concat(m.empty()) is equivalent to m`\r\n  * ∀m ∈ E, `m.empty().concat(m) is equivalent to m`\r\n\r\nHence E is a Monoid.\r\n\r\nAm I misinterpreting \"A value which has a Monoid must provide an `empty` method on itself or its `constructor` object\" in some way to allow this?"}}