No description, website, or topics provided.
Scala
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
project
src
.gitignore
.scalafmt.conf
.travis.yml
LICENSE
README.md
build.sbt
deploy.sbt.disabled
version.sbt

README.md

implicit-dependent-type

Join the chat at https://gitter.im/ThoughtWorksInc/implicit-dependent-type Build Status

implicit-dependent-type is a Scala compiler plugin that resolves dependent types from implicit type classes, especially useful when working with shapeless or other type-level programming libraries.

Setup

addCompilerPlugin("com.thoughtworks.implicit-dependent-type" %% "implicit-dependent-type" % "latest.release")

addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)

libraryDependencies += "com.chuusai" %% "shapeless" % "latest.release"

Foo[Bar]##Baz syntax

This plugin provides a syntactic sugar that substitutes all Foo[Bar]##Baz with shapeless.the.`Foo[Bar]`.Baz, which inlines resolved implicit type classes into type declaration positions.

import shapeless._

final case class Foo(bar: Int, baz: String)

val hlistForFoo: Generic[Foo]##Repr = 1 :: "xxx" :: HNil
val foo: Foo = Generic[Foo].from(hlistForFoo)

The above example equals to the following code:

import shapeless._

final case class Foo(bar: Int, baz: String)

val g = Generic[Foo]
val hlistForFoo: g.Repr = 1 :: "xxx" :: HNil
val foo: Foo = Generic[Foo].from(hlistForFoo)

As you see, without this plugin, Generic[Foo] is not a stable value, thus it is unable to be placed at a type position. You will have to assign it to a temporary variable g.

This plugin resolves this problem.

Foo @Bar syntax (since 2.0)

Another syntactic sugar provided by this plugin is Foo @Bar, which will be converted to shapeless.the.`Bar[Foo]`.`@`.

For example:

trait GetElement[A] {
  type `@`
}

implicit def getArrayElement[Element] = new GetElement[Array[Element]] {
  override type `@` = Element
}

implicit def getSeqElement[Element] = new GetElement[Seq[Element]] {
  override type `@` = Element
}

val i: Array[Int] @GetElement = 1 // OK
val s: Seq[String] @GetElement = "text" // OK

val d: Option[Double] @GetElement = 0.5 // Does not compile because no implicit GetElement[Option[Double]] found

In the above example, @GetElement acts as a type level function, calculating the element type of the given type.

Note that the Foo @Bar syntax only applied if Bar starts with an upper case character. Thus, this plugin does not affect built-in annotations like @specialize, @cps or @suspendable because they start with a lower case character.