All Projects → scalalandio → catnip

scalalandio / catnip

Licence: Apache-2.0 license
Static annotations for Kittens for people who don't like to write semiautomatic derivations into companion objects themselves.

Programming Languages

scala
5932 projects
shell
77523 projects

Projects that are alternatives of or similar to catnip

accelerator-core-js
Accelerator Core provides a simple way to integrate real-time audio/video into your web application using the OpenTok Platform
Stars: ✭ 24 (-36.84%)
Mutual labels:  annotations
catsay
🐱 💻 like cowsay but cats
Stars: ✭ 33 (-13.16%)
Mutual labels:  cats
2vcf
convert 23andme or Ancestry.com raw genotype calls into VCF format, with dbSNP annotations
Stars: ✭ 42 (+10.53%)
Mutual labels:  annotations
phpunit-injector
Injects services from a PSR-11 dependency injection container to PHPUnit test cases
Stars: ✭ 62 (+63.16%)
Mutual labels:  annotations
gum
Repository for the Georgetown University Multilayer Corpus (GUM)
Stars: ✭ 71 (+86.84%)
Mutual labels:  annotations
annotated
Schema generation using annotated entities and mappers
Stars: ✭ 19 (-50%)
Mutual labels:  annotations
PersianNER
Named-Entity Recognition in Persian Language
Stars: ✭ 48 (+26.32%)
Mutual labels:  annotations
freecli
Command line parsing library using Free Applicative
Stars: ✭ 29 (-23.68%)
Mutual labels:  cats
zf-dependency-injection
Advanced dependency injection for laminas framework
Stars: ✭ 17 (-55.26%)
Mutual labels:  annotations
simple-preferences
Android Library to simplify SharedPreferences use with code generation.
Stars: ✭ 48 (+26.32%)
Mutual labels:  annotations
AnnotationInject
Compile-time Swift dependency injection annotations
Stars: ✭ 40 (+5.26%)
Mutual labels:  annotations
graphql-metadata
Annotate your graphql schema with lightweight directives
Stars: ✭ 28 (-26.32%)
Mutual labels:  annotations
geantyref
Advanced generic type reflection library with support for working with AnnotatedTypes (for Java 8+)
Stars: ✭ 73 (+92.11%)
Mutual labels:  annotations
aptk
A toolkit project to enable you to build annotation processors more easily
Stars: ✭ 28 (-26.32%)
Mutual labels:  annotations
api-router
👨 RESTful router for your API in Nette Framework (@nette). Created either directly or via annotation.
Stars: ✭ 18 (-52.63%)
Mutual labels:  annotations
dart sealed
Dart and Flutter sealed class generator and annotations, with match methods and other utilities. There is also super_enum compatible API.
Stars: ✭ 16 (-57.89%)
Mutual labels:  annotations
aspecio
Aspecio, AOP Proxies for OSGi services
Stars: ✭ 14 (-63.16%)
Mutual labels:  annotations
soap-typescript
SOAP decorators for creating wsdl's and annotating services to provide metadata for node-soap
Stars: ✭ 20 (-47.37%)
Mutual labels:  annotations
Exact
An open source online platform for collaborative image labeling of almost everything
Stars: ✭ 47 (+23.68%)
Mutual labels:  annotations
pfps-examples
🏮 Standalone examples shown in the book "Practical FP in Scala: A hands-on approach"
Stars: ✭ 167 (+339.47%)
Mutual labels:  cats

catnip

Build Status Maven Central Scala.js License

Static annotations for Kittens for people who don't like to write semiautomatic derivations into companion objects themselves.

Usage

Add to your sbt (2.11, 2.12, 2.13):

libraryDependencies += "io.scalaland" %% "catnip" % catnipVersion // see Maven badge
// If you use Scala >= 2.13:
scalacOptions += "-Ymacro-annotations"
// If you use Scala 2.12 or 2.11:
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross sbt.CrossVersion.patch)

or, if you use Scala.js:

libraryDependencies += "io.scalaland" %%% "catnip" % catnipVersion // see Maven badge
// If you use Scala >= 2.13:
scalacOptions += "-Ymacro-annotations"
// If you use Scala 2.12 or 2.11:
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross sbt.CrossVersion.patch)

From now on you can add implicit Kittens-generated type classes for your case classes with a simple macro-annotation:

import io.scalaland.catnip._
import cats._
import cats.implicits._ // don't forget to import the right implicits!
import alleycats.std.all._ // might also come handy

@Semi(Eq, Monoid, Show) final case class Test(a: String)

Test("a") === Test("b") // false
Test("a") |+| Test("b") // Test("ab")
Test("a").show          // "Test(a = a)"

You can also test it with ammonite like:

interp.preConfigureCompiler(_.processArguments(List("-Ymacro-annotations"), true))

@

import $ivy.`io.scalaland::catnip:1.0.0`, io.scalaland.catnip._, cats._, cats.implicits._

@Semi(Eq, Monoid, Functor) final case class Test[A](a: A)

Test("a") === Test("b") // false
Test("a") |+| Test("b") // Test("ab")
Test("1").map(_.toInt)  // Test(1)

Implemented

cats.Eq, cats.PartialOrder, cats.Order, cats.Functor, cats.Foldable, cats.Traverse, cats.Show, cats.derived.ShowPretty, cats.Monoid, cats.MonoidK, cats.Semigroup, cats.SemigroupK, alleycats.Empty, alleycats.Pure.

Internals

Macro turns

@Semi(cats.Semigroup) final case class TestSemi(a: String)

@Semi(cats.SemigroupK, cats.Eq) final case class TestSemiK[A](a: List[A])

into

final case class TestSemi(a: String)
object TestSemi {
  implicit val _derived_cats_kernel_Semigroup = cats.derived.semi.semigroup[TestSemi]
}

final case class TestSemiK[A](a: List[A])
object TestSemiK {
  implicit val _derived_cats_SemigroupK = cats.derived.semi.semigroupK[TestSemiK];
  implicit def _derived_cats_kernel_Eq[A](implicit cats_kernel_Eq_a: cats.kernel.Eq[List[A]]) = cats.derived.semi.eq[TestSemiK[A]]
}

In order to do so it:

  • takes the companion object from the argument
  • turns it into a class name an dealias it (so CO should match the class!)
  • then reads derive.semi.conf
    • this class contains type class to kittens generator mappings
  • for plain types is just paste the body
  • for parametric types [A] is reuses TypeClass to create an implicit TypeClass[A] argument
  • in special cases like Show which would require additional type class (shapeless.Typeable[A]), they are defined in config after the generator function and separated by commas

Customizations

You should be able to extend the abilities of the macro by expanding the content of derive.semi.conf. You can create this file and add it to your library if you want Catnip to support it as all files with that name are looked through during compilation. When it comes to sbt it doesn't always export resources to Compile scope, so your configs might not be visible in your modules while they would be available in created JARs. (Creating somewhat inconsistent experience). Personally, I fixed this by adding something like

val myProject = project.in(file("my-project"))
  // other settings
  .settings(Compile / unmanagedResourceDirectories += baseDirectory.value / "../src/main/resources")

to sbt. This will make your customizations immediately available to your modules.

Take a look at an example project to see how customization works in practice.

Debugging

To debug you can use catnip.debug flag:

> sbt -Dcatnip.debug=debug # show info about derivation
> sbt -Dcatnip.debug=trace # show even more infor about derivation

Limitations

Type checker complains if you use type aliases from the same compilation unit

type X = cats.Eq; val X = cats.Eq
@Semi(X) final case class Test(a: String)
// scala.reflect.macros.TypecheckException: not found: type X

same if you rename type during import

import cats.{ Eq => X }
@Semi(X) final case class Test(a: String)
// scala.reflect.macros.TypecheckException: not found: type X

However, if you simply import definitions or aliases already defined somewhere else, you should have no issues.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].