{"action":"created","issue":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/4153","repository_url":"https://api.github.com/repos/lampepfl/dotty","labels_url":"https://api.github.com/repos/lampepfl/dotty/issues/4153/labels{/name}","comments_url":"https://api.github.com/repos/lampepfl/dotty/issues/4153/comments","events_url":"https://api.github.com/repos/lampepfl/dotty/issues/4153/events","html_url":"https://github.com/lampepfl/dotty/pull/4153","id":307343815,"number":4153,"title":"[Proposal] Typeclass Traits","user":{"login":"odersky","id":795990,"avatar_url":"https://avatars2.githubusercontent.com/u/795990?v=4","gravatar_id":"","url":"https://api.github.com/users/odersky","html_url":"https://github.com/odersky","followers_url":"https://api.github.com/users/odersky/followers","following_url":"https://api.github.com/users/odersky/following{/other_user}","gists_url":"https://api.github.com/users/odersky/gists{/gist_id}","starred_url":"https://api.github.com/users/odersky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odersky/subscriptions","organizations_url":"https://api.github.com/users/odersky/orgs","repos_url":"https://api.github.com/users/odersky/repos","events_url":"https://api.github.com/users/odersky/events{/privacy}","received_events_url":"https://api.github.com/users/odersky/received_events","type":"User","site_admin":false},"labels":[{"id":203754560,"url":"https://api.github.com/repos/lampepfl/dotty/labels/itype:language%20enhancement","name":"itype:language enhancement","color":"cc317c","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":107,"created_at":"2018-03-21T17:24:39Z","updated_at":"2018-04-06T09:39:40Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/lampepfl/dotty/pulls/4153","html_url":"https://github.com/lampepfl/dotty/pull/4153","diff_url":"https://github.com/lampepfl/dotty/pull/4153.diff","patch_url":"https://github.com/lampepfl/dotty/pull/4153.patch"},"body":"This is a proposal to support extension methods and typeclasses in a more direct and convenient way. It is based on #4114.\r\n\r\n### Status\r\n\r\n\r\nThis is a first draft proposal (consider it Pre-SIP stage).  None of the features that go beyond #4114 are implemented yet. \r\n\r\n### Rationale\r\n\r\nThere are two dominant styles of structuring Scala programs: Standard (object-oriented) class hierarchies or typeclass hierarchies encoded with implicit parameters. Standard class hierarchies lead to simpler code and allow to dispatch on the runtime type, which enables some optimizations that are hard to emulate with implicits. Typeclass hierarchies are more flexible: instances can be given independently of the implementing types and the implemented interfaces, and instances can be made conditional on other typeclass instances. \r\n\r\nUnfortunately, typeclass-oriented programming has a high upfront cost. It starts with the definitions of \"typeclasses\" themselves. Say you want to implement a typeclass for a `map` method (often called a `Functor`). The usage you want to support is:\r\n\r\n    xs.map(f)\r\n\r\nHowever, you can't define `map` as a unary method like this, not if it is part of a typeclass. Instead you need to define a binary version of map, along the following lines:\r\n    \r\n    trait Functor[F[_]] {\r\n      def map[A, B](f: A => B, xs: F[A]): F[B] = ...\r\n    }\r\n\r\nYou need another implicit class, to get back `map` as an infix operator. Something like this:\r\n\r\n    implicit class InfixMap[F[_]: Functor, A](private val x: F[A]) extends AnyVal {\r\n      def map(f: A => B): F[B] = implicitly[F].map(f, x)\r\n    }\r\n\r\nIt does the job, but at a cost of lots of boilerplate! The required boilerplate is very technical, advanced, and, I believe, frightening for a newcomer. The complexity of typeclasses does not end with their definition, either. It continues to the use sites, which typically need one extra type parameter per typeclass argument. Scala is a language set out to eliminate boilerplate and promote the simplest possible style of expression. But it seems in this area it has utterly failed to do so. \r\n\r\nhttps://github.com/mpilquist/simulacrum is macro library that removes a lot of the boilerplate. But it relies on \"macro paradise\" which has never been officially supported and has lost its maintainer https://contributors.scala-lang.org/t/stepping-down-as-the-maintainer-of-scalamacros-paradise/1703. The kind of annotation macros required by simulacrum will almost certainly only be supported in Dotty as code generation tools, requiring a separate build step. \r\n\r\nThe aim of this proposal is to\r\n\r\n - make typeclasses easy and pleasant to use.\r\n - remove the rift between standard class hierarchies and typeclass hierarchies. Both should be written in the same way and it should be possible to mix both styles and move fluidly between them. \r\n - in conjunction with opaque types, replace the lower-level constructs of value classes and implicit classes.\r\n\r\n### Details\r\n\r\nThe proposal is written up as a list of reference pages:\r\n\r\n 1. [Extension Methods](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/extension-methods.md)\r\n 2. [Instance Declarations](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/instance-declarations.md)\r\n 3. [Typeclass Traits](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/typeclass-traits.md)\r\n 4. [Common Declarations](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/common-declarations.md)\r\n 5. [Context Bounds](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/context-bounds.md)\r\n 6. [Parameterised Typeclass Traits](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/parameterized-typeclasses.md)\r\n 7. [Factored Instance Declarations](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/factored-instances.md)\r\n 8. [Local Coherence](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/local-coherence.md)\r\n 9. [Syntax and Type Checking](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/rules.md)\r\n 10. [Translation Scheme](https://github.com/dotty-staging/dotty/blob/add-common/docs/docs/reference/extend/translation.md)\r\n\r\nThe proposal was heavily inspired by Rust's traits and implementations. The main differences to Rust are\r\n\r\n - extensions are named instead of being anonymous\r\n - a tight integration with standard classes and traits\r\n - a transparent mapping to the underlying system of implicits\r\n - implied self parameters\r\n - direct support for higher kinds\r\n - local instead of global coherence\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/comments/379202754","html_url":"https://github.com/lampepfl/dotty/pull/4153#issuecomment-379202754","issue_url":"https://api.github.com/repos/lampepfl/dotty/issues/4153","id":379202754,"user":{"login":"etorreborre","id":10988,"avatar_url":"https://avatars2.githubusercontent.com/u/10988?v=4","gravatar_id":"","url":"https://api.github.com/users/etorreborre","html_url":"https://github.com/etorreborre","followers_url":"https://api.github.com/users/etorreborre/followers","following_url":"https://api.github.com/users/etorreborre/following{/other_user}","gists_url":"https://api.github.com/users/etorreborre/gists{/gist_id}","starred_url":"https://api.github.com/users/etorreborre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/etorreborre/subscriptions","organizations_url":"https://api.github.com/users/etorreborre/orgs","repos_url":"https://api.github.com/users/etorreborre/repos","events_url":"https://api.github.com/users/etorreborre/events{/privacy}","received_events_url":"https://api.github.com/users/etorreborre/received_events","type":"User","site_admin":false},"created_at":"2018-04-06T09:39:40Z","updated_at":"2018-04-06T09:39:40Z","author_association":"NONE","body":"@odersky I think your approach is definitely worth exploring and it is interesting to contrast what you are proposing with Rust's `self`. When you write:\r\n\r\n> except that the traits that can be implemented are limited because they cannot talk about the implementation type (i.e. This is missing).\r\n\r\nIndeed `This` is missing and I wonder what is the overall price of adding it (plus other consequences like the change with context bounds?), in terms of implementation, cognitive load, potential bugs, compared to introducing `typeclass/instance`. But talk is cheap and people convinced with a `typeclass/instance` approach should prepare a SIP so we can do side by side comparisons. I can offer to review such a SIP but I unfortunately don't have to time to write it down :-( (nor the skills I'm afraid). My hunch is that the second design will end up being easier to implement, teach and use."}}
{"actor":{"display_login":"etorreborre"}}