{"action":"created","comment":{"url":"https://api.github.com/repos/47deg/KEEP/pulls/comments/198461477","pull_request_review_id":132390678,"id":198461477,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5ODQ2MTQ3Nw==","diff_hunk":"@@ -237,60 +202,155 @@ fun addInts(a: Int, b: Int, with Monoid<Int>): Int = add(a, b)\n fun addInts(a: Int, b: Int): Int = with(intext.IntMonoid) { add(a, b) }\n ```\n \n-## Compile resolution rules\n+## Type Class Instance Rules\n \n-When the compiler finds a call site invoking a function that has type class instances constrains declared with `with` as in the example below:\n+Classical interfaces only allow the implementation of interfaces to occur when a type is defined. Type classes typically relax this rule and allow implementations outside of the type definition. When relaxinng this rule it is important to preserve the coherency we take for granted with classical interfaces.\n \n-Declaration: \n+For those reasons type class instances must be declared in one of two places:\n+\n+1. In the same file as the type class definition (interface-side implementation)\n+2. In the same file as the type being implemented (type-side implementation)\n+\n+All other instances are orphan instances and are not allowed. See [Appendix A](#Appendix-A) for a modification to this proposal that allows for orphan instances.\n+\n+Additionally a type class implementation must not conflict with any other already defined type class implementations; for the purposes of checking this we use the normal resolution rules.\n+\n+### Interface-Side Implementations\n+\n+This definition site is simple to implement and requires to rules except that the instances occurs in the same package. E.g. the following implementation is allowed\n ```kotlin\n-fun <A> add(a: A, b: A, with Monoid<A>): A = a.combine(b)\n+package foo.collections\n+\n+extension interface Monoid<A> {\n+   ...\n+}\n ```\n-Call site:\n+\n ```kotlin\n-extension class AddingInts {\n-  fun addInts(): Int = add(1, 2)\n+package foo.collections\n+\n+extension object : Monoid<String> {\n+   ...\n }\n ```\n-The compiler may choose the following order for resolving the evidence that a `Monoid<Int>` exists in scope.\n \n-1. Look in the most immediate scope for declarations of `with Monoid<Int>` in this case the function `addInts`\n+### Type-Side Implementations\n+\n+This definition site poses additional complications when you consider multi-parameter typeclasses.\n \n-This will compile because the responsibility of providing `Monoid<Int>` is passed into the callers of `addInts()`:\n ```kotlin\n-extension object AddingInts {\n-  fun addInts(with Monoid<Int>): Int = add(1, 2)\n+package foo.collections\n+\n+extension interface Isomorphism<A, B> {\n+   ...\n }\n ```\n \n-2. Look in the immediately outher class/interface scope for declarations of `with Monoid<Int>` in this case the class `AddingInts`:\n ```kotlin\n-extension class AddingInts(with Monoid<Int>) {\n-  fun addInts(): Int = add(1, 2)\n+package data.foo\n+\n+data class Foo(...)\n+extension class<A> : Isomorphism<Foo, A> {\n+   ...\n }\n ```\n-This will compile because the responsibility of providing `Monoid<Int>` is passed unto the callers of `AddingInts()`\n \n-3. Look in the import declarations for an explicitly imported instance that satisfies the constrain `Monoid<Int>`:\n ```kotlin\n-import intext.IntMonoid\n-extension object AddingInts {\n-  fun addInts(): Int = add(1, 2)\n+package data.bar\n+\n+data class Bar(...)\n+extension class<A> : Isomorphism<A, Bar> {\n+   ...\n }\n ```\n-This will compile because the responsibility of providing `Monoid<Int>` is satisfied by `import intext.IntMonoid`\n \n-4. Fail to compile if neither outer scopes nor explicit imports fail to provide evidence that there is a constrain satisfied by an instance in scope.\n+The above instances are each defined alongside their respective type definitions and yet they clearly conflict with each other. We will also run into quandaries once we consider generic types. We can crib some prior art from Rust<sup>1</sup> to help us out here.","path":"proposals/type-classes.md","position":226,"original_position":226,"commit_id":"00d6acafe8005b251ffd39e0e451eb089a70ad6c","original_commit_id":"00d6acafe8005b251ffd39e0e451eb089a70ad6c","user":{"login":"raulraja","id":456796,"node_id":"MDQ6VXNlcjQ1Njc5Ng==","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},"body":"Could we give just always precendence to local definitions flagged as internal and bail otherwise?\r\nWhat happens if the user includes two libraries both providing conflicting instances on top of his locally defined one?","created_at":"2018-06-27T11:39:12Z","updated_at":"2018-06-27T11:59:35Z","html_url":"https://github.com/47deg/KEEP/pull/6#discussion_r198461477","pull_request_url":"https://api.github.com/repos/47deg/KEEP/pulls/6","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/comments/198461477"},"html":{"href":"https://github.com/47deg/KEEP/pull/6#discussion_r198461477"},"pull_request":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/6"}}},"pull_request":{"url":"https://api.github.com/repos/47deg/KEEP/pulls/6","id":197473342,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3NDczMzQy","html_url":"https://github.com/47deg/KEEP/pull/6","diff_url":"https://github.com/47deg/KEEP/pull/6.diff","patch_url":"https://github.com/47deg/KEEP/pull/6.patch","issue_url":"https://api.github.com/repos/47deg/KEEP/issues/6","number":6,"state":"open","locked":false,"title":"Change Type Class Proposal to eliminate Implicit Arguments, make the interfaces coherent","user":{"login":"ClaireNeveu","id":1002726,"node_id":"MDQ6VXNlcjEwMDI3MjY=","avatar_url":"https://avatars3.githubusercontent.com/u/1002726?v=4","gravatar_id":"","url":"https://api.github.com/users/ClaireNeveu","html_url":"https://github.com/ClaireNeveu","followers_url":"https://api.github.com/users/ClaireNeveu/followers","following_url":"https://api.github.com/users/ClaireNeveu/following{/other_user}","gists_url":"https://api.github.com/users/ClaireNeveu/gists{/gist_id}","starred_url":"https://api.github.com/users/ClaireNeveu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ClaireNeveu/subscriptions","organizations_url":"https://api.github.com/users/ClaireNeveu/orgs","repos_url":"https://api.github.com/users/ClaireNeveu/repos","events_url":"https://api.github.com/users/ClaireNeveu/events{/privacy}","received_events_url":"https://api.github.com/users/ClaireNeveu/received_events","type":"User","site_admin":false},"body":"@raulraja Here is a PR with proposed rules for type class coherence. I've changed this slightly from my comment, mainly I have moved support for orphan instances to an appendix. I think it would make sense to be conservative in the initial proposal and add orphan handling in a separate KEEP once we get real world examples of how people use type classes.\r\n\r\nI've also added a few different ways those could be handled.\r\n\r\nFinally I removed the sections on dependency injection since that is an implicit arguments thing rather than a type class thing.\r\n\r\n### Syntax\r\nI haven't modified the syntax since I think semantics are the really important thing, but I personally think it would be better to mirror regular interfaces and move the type-class constraints to the type arguments, e.g.\r\n```kotlin\r\nfun <A, with Monoid<A>> add(a: A, b: A): A = TODO()\r\n```\r\n\r\n### Implementation Notes\r\n\r\nIf we forgo orphan handling, the implementation can be rather simple. When we compile a file we can simply attach the type class implementations to the companion objects of the type class or type being implemented. Then on resolution we can re-use existing mechanisms to easily look up attached instances.","created_at":"2018-06-26T15:58:33Z","updated_at":"2018-06-27T11:59:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ecb73aba02232c4f41a978907d9a4d115c54c910","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/47deg/KEEP/pulls/6/commits","review_comments_url":"https://api.github.com/repos/47deg/KEEP/pulls/6/comments","review_comment_url":"https://api.github.com/repos/47deg/KEEP/pulls/comments{/number}","comments_url":"https://api.github.com/repos/47deg/KEEP/issues/6/comments","statuses_url":"https://api.github.com/repos/47deg/KEEP/statuses/00d6acafe8005b251ffd39e0e451eb089a70ad6c","head":{"label":"ClaireNeveu:master","ref":"master","sha":"00d6acafe8005b251ffd39e0e451eb089a70ad6c","user":{"login":"ClaireNeveu","id":1002726,"node_id":"MDQ6VXNlcjEwMDI3MjY=","avatar_url":"https://avatars3.githubusercontent.com/u/1002726?v=4","gravatar_id":"","url":"https://api.github.com/users/ClaireNeveu","html_url":"https://github.com/ClaireNeveu","followers_url":"https://api.github.com/users/ClaireNeveu/followers","following_url":"https://api.github.com/users/ClaireNeveu/following{/other_user}","gists_url":"https://api.github.com/users/ClaireNeveu/gists{/gist_id}","starred_url":"https://api.github.com/users/ClaireNeveu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ClaireNeveu/subscriptions","organizations_url":"https://api.github.com/users/ClaireNeveu/orgs","repos_url":"https://api.github.com/users/ClaireNeveu/repos","events_url":"https://api.github.com/users/ClaireNeveu/events{/privacy}","received_events_url":"https://api.github.com/users/ClaireNeveu/received_events","type":"User","site_admin":false},"repo":{"id":136257013,"node_id":"MDEwOlJlcG9zaXRvcnkxMzYyNTcwMTM=","name":"KEEP","full_name":"ClaireNeveu/KEEP","owner":{"login":"ClaireNeveu","id":1002726,"node_id":"MDQ6VXNlcjEwMDI3MjY=","avatar_url":"https://avatars3.githubusercontent.com/u/1002726?v=4","gravatar_id":"","url":"https://api.github.com/users/ClaireNeveu","html_url":"https://github.com/ClaireNeveu","followers_url":"https://api.github.com/users/ClaireNeveu/followers","following_url":"https://api.github.com/users/ClaireNeveu/following{/other_user}","gists_url":"https://api.github.com/users/ClaireNeveu/gists{/gist_id}","starred_url":"https://api.github.com/users/ClaireNeveu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ClaireNeveu/subscriptions","organizations_url":"https://api.github.com/users/ClaireNeveu/orgs","repos_url":"https://api.github.com/users/ClaireNeveu/repos","events_url":"https://api.github.com/users/ClaireNeveu/events{/privacy}","received_events_url":"https://api.github.com/users/ClaireNeveu/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ClaireNeveu/KEEP","description":"Kotlin Evolution and Enhancement Process","fork":true,"url":"https://api.github.com/repos/ClaireNeveu/KEEP","forks_url":"https://api.github.com/repos/ClaireNeveu/KEEP/forks","keys_url":"https://api.github.com/repos/ClaireNeveu/KEEP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ClaireNeveu/KEEP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ClaireNeveu/KEEP/teams","hooks_url":"https://api.github.com/repos/ClaireNeveu/KEEP/hooks","issue_events_url":"https://api.github.com/repos/ClaireNeveu/KEEP/issues/events{/number}","events_url":"https://api.github.com/repos/ClaireNeveu/KEEP/events","assignees_url":"https://api.github.com/repos/ClaireNeveu/KEEP/assignees{/user}","branches_url":"https://api.github.com/repos/ClaireNeveu/KEEP/branches{/branch}","tags_url":"https://api.github.com/repos/ClaireNeveu/KEEP/tags","blobs_url":"https://api.github.com/repos/ClaireNeveu/KEEP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ClaireNeveu/KEEP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ClaireNeveu/KEEP/git/refs{/sha}","trees_url":"https://api.github.com/repos/ClaireNeveu/KEEP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ClaireNeveu/KEEP/statuses/{sha}","languages_url":"https://api.github.com/repos/ClaireNeveu/KEEP/languages","stargazers_url":"https://api.github.com/repos/ClaireNeveu/KEEP/stargazers","contributors_url":"https://api.github.com/repos/ClaireNeveu/KEEP/contributors","subscribers_url":"https://api.github.com/repos/ClaireNeveu/KEEP/subscribers","subscription_url":"https://api.github.com/repos/ClaireNeveu/KEEP/subscription","commits_url":"https://api.github.com/repos/ClaireNeveu/KEEP/commits{/sha}","git_commits_url":"https://api.github.com/repos/ClaireNeveu/KEEP/git/commits{/sha}","comments_url":"https://api.github.com/repos/ClaireNeveu/KEEP/comments{/number}","issue_comment_url":"https://api.github.com/repos/ClaireNeveu/KEEP/issues/comments{/number}","contents_url":"https://api.github.com/repos/ClaireNeveu/KEEP/contents/{+path}","compare_url":"https://api.github.com/repos/ClaireNeveu/KEEP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ClaireNeveu/KEEP/merges","archive_url":"https://api.github.com/repos/ClaireNeveu/KEEP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ClaireNeveu/KEEP/downloads","issues_url":"https://api.github.com/repos/ClaireNeveu/KEEP/issues{/number}","pulls_url":"https://api.github.com/repos/ClaireNeveu/KEEP/pulls{/number}","milestones_url":"https://api.github.com/repos/ClaireNeveu/KEEP/milestones{/number}","notifications_url":"https://api.github.com/repos/ClaireNeveu/KEEP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ClaireNeveu/KEEP/labels{/name}","releases_url":"https://api.github.com/repos/ClaireNeveu/KEEP/releases{/id}","deployments_url":"https://api.github.com/repos/ClaireNeveu/KEEP/deployments","created_at":"2018-06-06T01:54:11Z","updated_at":"2018-06-26T15:52:37Z","pushed_at":"2018-06-26T15:52:35Z","git_url":"git://github.com/ClaireNeveu/KEEP.git","ssh_url":"git@github.com:ClaireNeveu/KEEP.git","clone_url":"https://github.com/ClaireNeveu/KEEP.git","svn_url":"https://github.com/ClaireNeveu/KEEP","homepage":null,"size":263,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"47deg:master","ref":"master","sha":"6a10e93878bac748d156c86018986cb22e3860b7","user":{"login":"47deg","id":479857,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3OTg1Nw==","avatar_url":"https://avatars3.githubusercontent.com/u/479857?v=4","gravatar_id":"","url":"https://api.github.com/users/47deg","html_url":"https://github.com/47deg","followers_url":"https://api.github.com/users/47deg/followers","following_url":"https://api.github.com/users/47deg/following{/other_user}","gists_url":"https://api.github.com/users/47deg/gists{/gist_id}","starred_url":"https://api.github.com/users/47deg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/47deg/subscriptions","organizations_url":"https://api.github.com/users/47deg/orgs","repos_url":"https://api.github.com/users/47deg/repos","events_url":"https://api.github.com/users/47deg/events{/privacy}","received_events_url":"https://api.github.com/users/47deg/received_events","type":"Organization","site_admin":false},"repo":{"id":105564791,"node_id":"MDEwOlJlcG9zaXRvcnkxMDU1NjQ3OTE=","name":"KEEP","full_name":"47deg/KEEP","owner":{"login":"47deg","id":479857,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3OTg1Nw==","avatar_url":"https://avatars3.githubusercontent.com/u/479857?v=4","gravatar_id":"","url":"https://api.github.com/users/47deg","html_url":"https://github.com/47deg","followers_url":"https://api.github.com/users/47deg/followers","following_url":"https://api.github.com/users/47deg/following{/other_user}","gists_url":"https://api.github.com/users/47deg/gists{/gist_id}","starred_url":"https://api.github.com/users/47deg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/47deg/subscriptions","organizations_url":"https://api.github.com/users/47deg/orgs","repos_url":"https://api.github.com/users/47deg/repos","events_url":"https://api.github.com/users/47deg/events{/privacy}","received_events_url":"https://api.github.com/users/47deg/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/47deg/KEEP","description":"Kotlin Evolution and Enhancement Process","fork":true,"url":"https://api.github.com/repos/47deg/KEEP","forks_url":"https://api.github.com/repos/47deg/KEEP/forks","keys_url":"https://api.github.com/repos/47deg/KEEP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/47deg/KEEP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/47deg/KEEP/teams","hooks_url":"https://api.github.com/repos/47deg/KEEP/hooks","issue_events_url":"https://api.github.com/repos/47deg/KEEP/issues/events{/number}","events_url":"https://api.github.com/repos/47deg/KEEP/events","assignees_url":"https://api.github.com/repos/47deg/KEEP/assignees{/user}","branches_url":"https://api.github.com/repos/47deg/KEEP/branches{/branch}","tags_url":"https://api.github.com/repos/47deg/KEEP/tags","blobs_url":"https://api.github.com/repos/47deg/KEEP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/47deg/KEEP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/47deg/KEEP/git/refs{/sha}","trees_url":"https://api.github.com/repos/47deg/KEEP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/47deg/KEEP/statuses/{sha}","languages_url":"https://api.github.com/repos/47deg/KEEP/languages","stargazers_url":"https://api.github.com/repos/47deg/KEEP/stargazers","contributors_url":"https://api.github.com/repos/47deg/KEEP/contributors","subscribers_url":"https://api.github.com/repos/47deg/KEEP/subscribers","subscription_url":"https://api.github.com/repos/47deg/KEEP/subscription","commits_url":"https://api.github.com/repos/47deg/KEEP/commits{/sha}","git_commits_url":"https://api.github.com/repos/47deg/KEEP/git/commits{/sha}","comments_url":"https://api.github.com/repos/47deg/KEEP/comments{/number}","issue_comment_url":"https://api.github.com/repos/47deg/KEEP/issues/comments{/number}","contents_url":"https://api.github.com/repos/47deg/KEEP/contents/{+path}","compare_url":"https://api.github.com/repos/47deg/KEEP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/47deg/KEEP/merges","archive_url":"https://api.github.com/repos/47deg/KEEP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/47deg/KEEP/downloads","issues_url":"https://api.github.com/repos/47deg/KEEP/issues{/number}","pulls_url":"https://api.github.com/repos/47deg/KEEP/pulls{/number}","milestones_url":"https://api.github.com/repos/47deg/KEEP/milestones{/number}","notifications_url":"https://api.github.com/repos/47deg/KEEP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/47deg/KEEP/labels{/name}","releases_url":"https://api.github.com/repos/47deg/KEEP/releases{/id}","deployments_url":"https://api.github.com/repos/47deg/KEEP/deployments","created_at":"2017-10-02T17:41:21Z","updated_at":"2018-06-19T01:41:07Z","pushed_at":"2018-06-26T15:58:33Z","git_url":"git://github.com/47deg/KEEP.git","ssh_url":"git@github.com:47deg/KEEP.git","clone_url":"https://github.com/47deg/KEEP.git","svn_url":"https://github.com/47deg/KEEP","homepage":null,"size":281,"stargazers_count":2,"watchers_count":2,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":2,"open_issues":1,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/6"},"html":{"href":"https://github.com/47deg/KEEP/pull/6"},"issue":{"href":"https://api.github.com/repos/47deg/KEEP/issues/6"},"comments":{"href":"https://api.github.com/repos/47deg/KEEP/issues/6/comments"},"review_comments":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/6/comments"},"review_comment":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/47deg/KEEP/pulls/6/commits"},"statuses":{"href":"https://api.github.com/repos/47deg/KEEP/statuses/00d6acafe8005b251ffd39e0e451eb089a70ad6c"}},"author_association":"NONE"}}
{"actor":{"display_login":"raulraja"}}