{"action":"created","issue":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/1920","repository_url":"https://api.github.com/repos/ocaml/ocaml","labels_url":"https://api.github.com/repos/ocaml/ocaml/issues/1920/labels{/name}","comments_url":"https://api.github.com/repos/ocaml/ocaml/issues/1920/comments","events_url":"https://api.github.com/repos/ocaml/ocaml/issues/1920/events","html_url":"https://github.com/ocaml/ocaml/pull/1920","id":342949195,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAyNzI5MTgx","number":1920,"title":"Add Functor, Applicative, Monad, Identity, and Option modules","user":{"login":"TheAspiringHacker","id":30581223,"node_id":"MDQ6VXNlcjMwNTgxMjIz","avatar_url":"https://avatars0.githubusercontent.com/u/30581223?v=4","gravatar_id":"","url":"https://api.github.com/users/TheAspiringHacker","html_url":"https://github.com/TheAspiringHacker","followers_url":"https://api.github.com/users/TheAspiringHacker/followers","following_url":"https://api.github.com/users/TheAspiringHacker/following{/other_user}","gists_url":"https://api.github.com/users/TheAspiringHacker/gists{/gist_id}","starred_url":"https://api.github.com/users/TheAspiringHacker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheAspiringHacker/subscriptions","organizations_url":"https://api.github.com/users/TheAspiringHacker/orgs","repos_url":"https://api.github.com/users/TheAspiringHacker/repos","events_url":"https://api.github.com/users/TheAspiringHacker/events{/privacy}","received_events_url":"https://api.github.com/users/TheAspiringHacker/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-07-20T02:15:24Z","updated_at":"2018-07-29T01:34:28Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/ocaml/ocaml/pulls/1920","html_url":"https://github.com/ocaml/ocaml/pull/1920","diff_url":"https://github.com/ocaml/ocaml/pull/1920.diff","patch_url":"https://github.com/ocaml/ocaml/pull/1920.patch"},"body":"Monads are a frequent used in functional code, including several third-party OCaml libraries, such as Jane Street's alternative standard libraries and Lwt. I am proposing the addition of monads, along with functors and applicatives, to the standard library, to provide a uniform interface. As the Monad module uses the more generalized monad transformers, I am also including an Identity module for the identity monad. Finally, I am including an Option module that demonstrates use of the Functor, Applicative, Monad, and Identity modules and provides convenience functions that may be used instead of pattern matching the option value.\r\n\r\nThe Functor, Applicative, and Monad modules follow the standard library's pattern of having a signature S as well as a functor Make, which in this case derives functions given a minimal definition.\r\n\r\nOne bikeshedding issue is that \"functor\" in OCaml means \"higher-order module,\" and having a Functor module with the Haskell definition may cause confusion. Perhaps Functor could be renamed to Mappable?\r\n\r\nI am considering the addition of an infix map operator. In Haskell, the operator is `<$>` as a reference to the `$` operator. OCaml's equivalent to `$` is `@@`, so should the infix map be named `<@@>`, or is this name too long to be convenient?\r\n\r\nI am also considering the addition of Kleisli composition to the Monad module. What should the function be named? Haskell uses `>=>` and `<=<`, but I suggest the more descriptive names `compose` or `compose_m`.\r\n"},"comment":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/comments/408645726","html_url":"https://github.com/ocaml/ocaml/pull/1920#issuecomment-408645726","issue_url":"https://api.github.com/repos/ocaml/ocaml/issues/1920","id":408645726,"node_id":"MDEyOklzc3VlQ29tbWVudDQwODY0NTcyNg==","user":{"login":"TheAspiringHacker","id":30581223,"node_id":"MDQ6VXNlcjMwNTgxMjIz","avatar_url":"https://avatars0.githubusercontent.com/u/30581223?v=4","gravatar_id":"","url":"https://api.github.com/users/TheAspiringHacker","html_url":"https://github.com/TheAspiringHacker","followers_url":"https://api.github.com/users/TheAspiringHacker/followers","following_url":"https://api.github.com/users/TheAspiringHacker/following{/other_user}","gists_url":"https://api.github.com/users/TheAspiringHacker/gists{/gist_id}","starred_url":"https://api.github.com/users/TheAspiringHacker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheAspiringHacker/subscriptions","organizations_url":"https://api.github.com/users/TheAspiringHacker/orgs","repos_url":"https://api.github.com/users/TheAspiringHacker/repos","events_url":"https://api.github.com/users/TheAspiringHacker/events{/privacy}","received_events_url":"https://api.github.com/users/TheAspiringHacker/received_events","type":"User","site_admin":false},"created_at":"2018-07-29T01:34:28Z","updated_at":"2018-07-29T01:34:28Z","author_association":"NONE","body":"Mr. Seri,\n\nThank you for your feedback. I'm sorry for not responding sooner. I just checked my email today. (A fault that I will fix is me not checking my email enough.) I checked my PR discussion page every day, but for a reason that I don't yet know, your reply does not appear on GitHub for me.\n\n> As much as I like these higher constructions, in OCaml they are not as essential as in Haskell and many people could be not used to them and their meaning. Look for example at how extensive is the documentation of the monad module in [bap](https://github.com/BinaryAnalysisPlatform/bap):\n> https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/monads/monads.mli\n>\n> I think the lack of combinators for certain types provided by the standard library is an annoyance (like having to require rresult to be able to have combinators for the result type or having to write the ones for the option type all the time, unless you want to rely on one for the standard libraries) but I am not convinced these algebraic constructions should be in the ocaml standard library yet (maybe we should wait to see how things need to change with effects, modular implicits and the new flambda):\n\nIn terms of evaluating the changes to the standard library, I think that it's worth separating the addition of Functor, Applicative, and Monad interfaces from the addition of an Option module, as the former is more radical than the latter. My main impetus to make this PR is my annoyance at the lack of functions to abstract away pattern matching over optional values, and I figured that if I was going to implement the functions in a PR, I ought to be thorough and officially define functors, applicatives, and monads. As an added benefit, by defining monad transformers and the identity monad, the standard library gets the identity function via the identity monad's return and function composition via its Kleisli composition. However, perhaps option deserves a module, but functors, applicatives, and monads don't?\n\n> - there is a clash of names and meanings, that may require rethinking the interface\n> - there is the issue of precedence of the operators, that depends on the character used instead of being associable to each operator\n> - there is a question of “balance”, in the sense that one could go all the way and have a comprehensive interface like https://github.com/IndiscriminateCoding/clarity or keep it small. In this case I think we should make it a bit more comprehensive than what it is and consider what from e.g. Semigroup, Monoid, Foldable, Traversable and Alternative to include. And add the various implementations for Options, Results, Lists, Arrays, Hashtables and Maps.\n> - there is a question of overhead if we swap the current implementation with implementations that are behind multiple levels of indirections (maybe it‘s not a problem, I am not an expert)\n\n- By \"a clash of names and meanings,\" are you referring to the meaning of \"functor\" or something else that I'm missing? If the former, what do you think of the name \"Mappable?\" On a tangent, I'd like to remark that \"map\" has a name clash between the dictionary data structure and the structure-preserving operation of type (a -> b) -> f a -> f b, yet programmers that use both meanings of map don't seem to be confused, even when the OCaml standard library defines a map function for maps!\n\n- All the operators that I have introduced start with > or <, so they are left-associative and have a precedence as described here: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html. As a comparison, in Haskell, >>=, <*>, and <$> are all left-associative, with <*> and <$> binding tighter than >>=. I don't see the precedence as an issue; the worst inconvenience is the need for parentheses, which aren't even necessary when chaining the same operator. I'd say that explicit parentheses can also be seen positively, and the fact that the OCaml operators all have the same precedence makes OCaml's treatment of them during parsing easier to remember than Haskell's treatment of them.\n\n- I am personally open to having more \"typeclass\" style interfaces, but I think that the discussion and decision should be made by the OCaml developers, not me. (Unless, of course, you are addressing this email to everyone in general. I'm replying to it as a conversation between us only because it isn't appearing on GitHub, at least for me, and I haven't received any other responses, either on GitHub or in my email.) If this PR gets approval, I will definitely make modules such as List and Array conform to the monad interface.\n\n- When I wrote the auto-derivation of the interface, I did have concerns about efficiency. For example, maps over lists would be defined by creating lists of length one via monadic bind and then concatenating them, as opposed to simply iterating over the list. As a comparison, Jane Street's standard library has an option for providing a custom map implementation. I was thinking of having multiple functors that derive their interfaces from different user-supplied definitions. With the PR in its current form, to override the default implementation, users would simply define the module members themselves rather than writing `include <output of deriver functor>`, at the cost of having to explicitly define the members that do use the deriver functor's definition. One solution for this ergonomics problem would be the ability to include a module (or signature) while listing members to exclude, but perhaps this idea belongs in another discussion. The indirection overhead from monad transformers could perhaps be alleviated by defining the identity monad's map and <@@> functions as external functions that use the primitive OCaml function application instruction \"%apply,\" and bind as the primitive instruction \"%revapply.\" I'm also not an expert on the OCaml internals, so I don't know what would be optimized away.\n\nAdditionally, do you happen to know why I'm not seeing your response on GitHub? I apologize in advance if the reason is something that I should have known. In the case that I'm not the only one who can't see your reply on GitHub, I definitely think that it deserves to be public on GitHub and read by others.\n\nMany thanks,\nTheAspiringHacker\n\nSent with [ProtonMail](https://protonmail.com) Secure Email.\n\n‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐\nOn July 20, 2018 9:30 AM, Marcello Seri <notifications@github.com> wrote:\n\n> I had a brief look for curiosity. It‘s nice and simple but I think the documentation should be way more detailed and probably it would be good to provide usage examples.\n>\n> As much as I like these higher constructions, in OCaml they are not as essential as in Haskell and many people could be not used to them and their meaning. Look for example at how extensive is the documentation of the monad module in [bap](https://github.com/BinaryAnalysisPlatform/bap):\n> https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/monads/monads.mli\n>\n> I think the lack of combinators for certain types provided by the standard library is an annoyance (like having to require rresult to be able to have combinators for the result type or having to write the ones for the option type all the time, unless you want to rely on one for the standard libraries) but I am not convinced these algebraic constructions should be in the ocaml standard library yet (maybe we should wait to see how things need to change with effects, modular implicits and the new flambda):\n>\n> - there is a clash of names and meanings, that may require rethinking the interface\n> - there is the issue of precedence of the operators, that depends on the character used instead of being associable to each operator\n> - there is a question of “balance”, in the sense that one could go all the way and have a comprehensive interface like https://github.com/IndiscriminateCoding/clarity or keep it small. In this case I think we should make it a bit more comprehensive than what it is and consider what from e.g. Semigroup, Monoid, Foldable, Traversable and Alternative to include. And add the various implementations for Options, Results, Lists, Arrays, Hashtables and Maps.\n> - there is a question of overhead if we swap the current implementation with implementations that are behind multiple levels of indirections (maybe it‘s not a problem, I am not an expert)\n>\n> I only had a brief look and that is what came to mind. Also, if the common feeling is that we should integrate it to the standard library, it would probably be good to review Base, Core, Containers and Batteries to see what they all implement and how. And find what interfaces and helpers are more commonly used/required.\n>\n> —\n> You are receiving this because you authored the thread.\n> Reply to this email directly, [view it on GitHub](https://github.com/ocaml/ocaml/pull/1920#issuecomment-406601174), or [mute the thread](https://github.com/notifications/unsubscribe-auth/AdKh5--_YQ7xNqx45rbCIy-oOEmlmNc9ks5uIdtygaJpZM4VXWdr)."}}
{"actor":{"display_login":"TheAspiringHacker"}}