{"action":"created","issue":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/5538","repository_url":"https://api.github.com/repos/lampepfl/dotty","labels_url":"https://api.github.com/repos/lampepfl/dotty/issues/5538/labels{/name}","comments_url":"https://api.github.com/repos/lampepfl/dotty/issues/5538/comments","events_url":"https://api.github.com/repos/lampepfl/dotty/issues/5538/events","html_url":"https://github.com/lampepfl/dotty/issues/5538","id":385556227,"node_id":"MDU6SXNzdWUzODU1NTYyMjc=","number":5538,"title":"Implicit cases in enum?","user":{"login":"ctongfei","id":5746409,"node_id":"MDQ6VXNlcjU3NDY0MDk=","avatar_url":"https://avatars1.githubusercontent.com/u/5746409?v=4","gravatar_id":"","url":"https://api.github.com/users/ctongfei","html_url":"https://github.com/ctongfei","followers_url":"https://api.github.com/users/ctongfei/followers","following_url":"https://api.github.com/users/ctongfei/following{/other_user}","gists_url":"https://api.github.com/users/ctongfei/gists{/gist_id}","starred_url":"https://api.github.com/users/ctongfei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ctongfei/subscriptions","organizations_url":"https://api.github.com/users/ctongfei/orgs","repos_url":"https://api.github.com/users/ctongfei/repos","events_url":"https://api.github.com/users/ctongfei/events{/privacy}","received_events_url":"https://api.github.com/users/ctongfei/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-11-29T03:38:59Z","updated_at":"2018-11-30T19:45:53Z","closed_at":"2018-11-30T19:45:53Z","author_association":"NONE","body":"This is inspired by #5495 .\r\n\r\nShould we allow `implicit` on `enum` `case`s? As @milessabin has stated, we could use an enum as a shapeless `Poly` with implicit cases corresponding to the `Case`'s of the `Poly`.\r\n\r\nFor example, we have the following typelevel function that computes the index of a type in an `HList`:\r\n```scala\r\n\r\ntrait IndexOf[A, U] extends DepFn0 {\r\n  type Out <: Nat\r\n  def toInt: Int\r\n}\r\n\r\nobject IndexOf {\r\n\r\n  def apply[A, U](implicit o: IndexOf[A, U]): Aux[A, U, o.Out] = o\r\n  type Aux[A, U, I <: Nat] = IndexOf[A, U] { type Out = I }\r\n\r\n  implicit def case0[At <: HList, U]: Aux[U :: At, U, _0] =\r\n    new IndexOf[U :: At, U] {\r\n      type Out = _0\r\n      def apply() = Nat._0\r\n      def toInt = 0\r\n    }\r\n\r\n  implicit def caseN[At <: HList, Ah, U, I <: Nat]\r\n  (implicit p: IndexOf.Aux[At, U, I]): Aux[Ah :: At, U, Succ[I]] =\r\n    new IndexOf[Ah :: At, U] {\r\n      type Out = Succ[I]\r\n      def apply() = Succ[I]()\r\n      def toInt = p.toInt + 1\r\n    }\r\n}\r\n```\r\n\r\nThis is quite verbose. Using `implicit case`s, I hope that this could be simplified to something like this:\r\n```scala\r\n\r\nenum IndexOf[A, U] extends DepFn0 {\r\n  type Out <: Nat\r\n  def toInt: Int\r\n\r\n  implicit case Case0[At <: HList, U] extends IndexOf[U :: At, U] {\r\n      type Out = _0\r\n      def apply() = Nat._0\r\n      def toInt = 0\r\n    }\r\n\r\n  implicit case CaseN[At <: HList, Ah, U, I <: Nat]\r\n  (implicit p: IndexOf.Aux[At, U, I]) extends IndexOf[Ah :: At, U] {\r\n      type Out = Succ[I]\r\n      def apply() = Succ[I]()\r\n      def toInt = p.toInt + 1\r\n    }\r\n\r\n}\r\n\r\n```\r\nwhere each `implicit case` corresponds to a clause (as in programming in Prolog).\r\n\r\nWhen desugaring, each `case` is turned into a class in the `enum`. Since `implicit class` in Scala is treated as a class and an `implicit def` (that converts an element to the implicit class wrapper), we could desugar each `implicit case` into a class and an `implicit def`. For example, the above could be desugared as:\r\n```scala\r\n\r\nenum IndexOf[A, U] extends DepFn0 {\r\n  type Out <: Nat\r\n  def toInt: Int\r\n\r\n  class Case0[At <: HList, U] extends IndexOf[U :: At, U] {\r\n      type Out = _0\r\n      def apply() = Nat._0\r\n      def toInt = 0\r\n    }\r\n\r\n class CaseN[At <: HList, Ah, U, I <: Nat]\r\n  (implicit p: IndexOf.Aux[At, U, I]) extends IndexOf[Ah :: At, U] {\r\n      type Out = Succ[I]\r\n      def apply() = Succ[I]()\r\n      def toInt = p.toInt + 1\r\n    }\r\n\r\n}\r\n\r\nobject IndexOf {\r\n  implicit def Case0$[At <: HList, U]: Case0[At, U] = new Case0()\r\n  implicit def CaseN$[At <: HList, Ah, U, I <: Nat](implicit p: IndexOf.Aux[At, U, I]): CaseN[Ah :: At, U, Succ[I]] = new CaseN()\r\n}\r\n\r\n```\r\n\r\nOr I wonder what match-types would enable us in this situation?"},"comment":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/comments/443318065","html_url":"https://github.com/lampepfl/dotty/issues/5538#issuecomment-443318065","issue_url":"https://api.github.com/repos/lampepfl/dotty/issues/5538","id":443318065,"node_id":"MDEyOklzc3VlQ29tbWVudDQ0MzMxODA2NQ==","user":{"login":"ctongfei","id":5746409,"node_id":"MDQ6VXNlcjU3NDY0MDk=","avatar_url":"https://avatars1.githubusercontent.com/u/5746409?v=4","gravatar_id":"","url":"https://api.github.com/users/ctongfei","html_url":"https://github.com/ctongfei","followers_url":"https://api.github.com/users/ctongfei/followers","following_url":"https://api.github.com/users/ctongfei/following{/other_user}","gists_url":"https://api.github.com/users/ctongfei/gists{/gist_id}","starred_url":"https://api.github.com/users/ctongfei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ctongfei/subscriptions","organizations_url":"https://api.github.com/users/ctongfei/orgs","repos_url":"https://api.github.com/users/ctongfei/repos","events_url":"https://api.github.com/users/ctongfei/events{/privacy}","received_events_url":"https://api.github.com/users/ctongfei/received_events","type":"User","site_admin":false},"created_at":"2018-11-30T19:45:53Z","updated_at":"2018-11-30T19:45:53Z","author_association":"NONE","body":"@OlivierBlanvillain Thanks for the explanation. Match types indeed seem to be the more elegant solution."}}
{"actor":{"display_login":"ctongfei"}}