{"action":"created","issue":{"url":"https://api.github.com/repos/arrow-kt/arrow/issues/811","repository_url":"https://api.github.com/repos/arrow-kt/arrow","labels_url":"https://api.github.com/repos/arrow-kt/arrow/issues/811/labels{/name}","comments_url":"https://api.github.com/repos/arrow-kt/arrow/issues/811/comments","events_url":"https://api.github.com/repos/arrow-kt/arrow/issues/811/events","html_url":"https://github.com/arrow-kt/arrow/pull/811","id":316539711,"number":811,"title":"Direct type class `syntax` over concrete data types","user":{"login":"raulraja","id":456796,"avatar_url":"https://avatars3.githubusercontent.com/u/456796?v=4","gravatar_id":"","url":"https://api.github.com/users/raulraja","html_url":"https://github.com/raulraja","followers_url":"https://api.github.com/users/raulraja/followers","following_url":"https://api.github.com/users/raulraja/following{/other_user}","gists_url":"https://api.github.com/users/raulraja/gists{/gist_id}","starred_url":"https://api.github.com/users/raulraja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulraja/subscriptions","organizations_url":"https://api.github.com/users/raulraja/orgs","repos_url":"https://api.github.com/users/raulraja/repos","events_url":"https://api.github.com/users/raulraja/events{/privacy}","received_events_url":"https://api.github.com/users/raulraja/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2018-04-22T01:20:12Z","updated_at":"2018-05-17T16:46:59Z","closed_at":null,"author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/arrow-kt/arrow/pulls/811","html_url":"https://github.com/arrow-kt/arrow/pull/811","diff_url":"https://github.com/arrow-kt/arrow/pull/811.diff","patch_url":"https://github.com/arrow-kt/arrow/pull/811.patch"},"body":"The following PR adds a `syntax` DSL for all data types that arrow exposes type class instances for.\r\n\r\nThis DSL allows users to not worry about knowing if `binding`, `flatMap` etc are in `Monad`, or what any other combinator they plan on using belongs to a certain type class.\r\n\r\nIt eliminates the need to explicitly refer to the instances inside the data type companion.\r\n\r\nUntil now users where forced to do things like:\r\n```kotlin\r\nOption.applicative().map(Option(1), Option(1), Option(1), { (a, b, c) -> a + b + c }) //Option(3)\r\nOption.monad().binding {\r\n  val a = Option(1).bind()\r\n  val b = Option(a + 1).bind()\r\n  a + b\r\n} \r\n// Option(3)\r\nOption.functor()...\r\nOption.traverse()...\r\n```\r\nInstead with the syntax DSL most used type classes that the data type provides instances for are bundled as the single `this` scope of the contained `syntax` function.\r\nThe scope contains all extension functions and static functions that the type classes define and are available to use within the user provided block.\r\n```kotlin\r\nimport arrow.instances.*\r\n\r\nOption syntax { //`this` is Monad, Applicative, Functor, Traverse, etc...\r\n  binding { ... }\r\n  map(....)\r\n  traverse(...)\r\n}\r\n\r\nEither<String>() syntax { //`this` is Monad, Applicative, Functor, Traverse, etc...\r\n  binding { ... }\r\n  map(....)\r\n  traverse(...)\r\n}\r\n```\r\n\r\nThe docs contain now instructions for users wanting to provide a similar DSL for their custom data type and it looks like this:\r\n\r\n> If you defined your own instances over your own data types and wish to use a similar `syntax` DSL you can do so for both types with a single type argument such as `Option`:\r\n\r\n```kotlin\r\nobject OptionContext : OptionMonadErrorInstance, OptionTraverseInstance {\r\n  override fun <A, B> Kind<ForOption, A>.map(f: (A) -> B): Option<B> =\r\n    fix().map(f)\r\n}\r\n\r\ninfix fun <A> Option.Companion.syntax(f: OptionContext.() -> A): A =\r\n  f(OptionContext)\r\n```\r\n\r\n> Or for types that require partial application of some of their type arguments such as `Either<L, R>` where `L` needs to be partially applied\r\n\r\n```kotlin\r\nclass EitherContext<L> : EitherMonadErrorInstance<L>, EitherTraverseInstance<L> {\r\n  override fun <A, B> Kind<EitherPartialOf<L>, A>.map(f: (A) -> B): Either<L, B> =\r\n    fix().map(f)\r\n}\r\n\r\nclass EitherContextPartiallyApplied<L> {\r\n  infix fun <A> syntax(f: EitherContext<L>.() -> A): A =\r\n    f(EitherContext())\r\n}\r\n\r\nfun <L> Either(): EitherContextPartiallyApplied<L> =\r\n  EitherContextPartiallyApplied()\r\n```"},"comment":{"url":"https://api.github.com/repos/arrow-kt/arrow/issues/comments/389933447","html_url":"https://github.com/arrow-kt/arrow/pull/811#issuecomment-389933447","issue_url":"https://api.github.com/repos/arrow-kt/arrow/issues/811","id":389933447,"user":{"login":"ersin-ertan","id":4809853,"avatar_url":"https://avatars2.githubusercontent.com/u/4809853?v=4","gravatar_id":"","url":"https://api.github.com/users/ersin-ertan","html_url":"https://github.com/ersin-ertan","followers_url":"https://api.github.com/users/ersin-ertan/followers","following_url":"https://api.github.com/users/ersin-ertan/following{/other_user}","gists_url":"https://api.github.com/users/ersin-ertan/gists{/gist_id}","starred_url":"https://api.github.com/users/ersin-ertan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ersin-ertan/subscriptions","organizations_url":"https://api.github.com/users/ersin-ertan/orgs","repos_url":"https://api.github.com/users/ersin-ertan/repos","events_url":"https://api.github.com/users/ersin-ertan/events{/privacy}","received_events_url":"https://api.github.com/users/ersin-ertan/received_events","type":"User","site_admin":false},"created_at":"2018-05-17T16:46:59Z","updated_at":"2018-05-17T16:46:59Z","author_association":"CONTRIBUTOR","body":"Proposal to change `syntax` to `instances` because:\r\n- `instances` plural, when paired with a data type named as a singular ex.`Option instances` will hopefully be enough to avoid naming clashes with the OOP concept of instantiation(though one may still wrongly assume that a list of instances is being returned)\r\n- `instances` acts like special version of Kotlins scoped function `with(...)`, allowing you to call the functions of the data type's available instances, so instead of writing `withAvailableInstancesOf(Option) { ... }`, the word `instances` provides enough context for the representation"}}
{"actor":{"display_login":"ersin-ertan"}}