question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Disable automatic derivation by default

See original GitHub issue

#304 was closed for an unrelated reason, however the issue remains.

(copied from https://github.com/pureconfig/pureconfig/issues/304#issuecomment-407960683).

Automatic derivation makes the field names etc. part of the API, which is not ideal. My team uses the explicit approach in similar cases (JSON codecs, etc.) - any encoding should be performed by an explicitly specified codec, and missing codec should cause a compilation error. Thus we need an option to disable automatic derivation entirely.

One way to achieve that (which is what circe project does) would be to remove DerivedReaders/DerivedWriters from ConfigReader/ConfigWriter objects, and make them accessible through an explicit import of some package object. We can even move those to a separate module, getting rid of the shapeless dependency in core. This would make this library a lot more flexible, at the cost of adding an import to the existing code.

UPD: to clarify, this issue is about shapeless-powered derivation for arbitrary ADTs. Map/Option/TraversableOnce typeclass instances should remain available by default.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:5
  • Comments:33 (16 by maintainers)

github_iconTop GitHub Comments

2reactions
fommilcommented, Aug 3, 2018

BTW, to add some numbers on this. In just our functional tests (15 files) of just one project, this bug is making us take 82s instead of 8s to compile.

I have monkey patched the Derived* classes to remove the implicit keyword, effectively disabling shapeless yet retaining binary compatibility.

I am in the process of writing a magnolia based deriver for ConfigReader, to be semi-auto combined with @deriving, that I expect to deliver a (max) 90% reduction in compiletime.

I’m going to use this as an example in my book about why full auto (and especially shapeless) should never be enabled by default on a typeclass 😉

1reaction
fommilcommented, Aug 8, 2018

BTW, for the benefit of anybody who is wondering how I fixed this in my work codebase:

  1. copy the exact version of DerivedReaders.scala from this repo into your project
  2. replace implicit def with def and implicit final with final everywhere in this file.
  3. introduce the below orphans.scala (note that I’ve removed superfluous Lazy and Derivation wrappers. BTW, your F doesn’t need to extend Traversable.)
  4. install magnolia 0.9.1 and use the belowe magnolia.scala
  5. install https://gitlab.com/fommil/scalaz-deriving with the below deriving.conf in resources
// orphans.scala
package pureconfig

object orphans {
  implicit def deriveOption[T: ConfigReader]: ConfigReader[Option[T]] =
    DerivedReaders.deriveOption[T]

  implicit def deriveTraversable[T: ConfigReader, F[T] <: Traversable[T]](
    implicit CBF: collection.generic.CanBuildFrom[F[T], T, F[T]]
  ): ConfigReader[F[T]] = DerivedReaders.deriveTraversable

  implicit def deriveMap[T: ConfigReader]: ConfigReader[Map[String, T]] =
    DerivedReaders.deriveMap[T]

  final implicit class ConfigReaderXMap[A](val self: ConfigReader[A]) extends AnyVal {
    def xmap[B](f: A => B, g: B => A): ConfigReader[B] = self.map(f)
  }
}
// magnolia.scala
package pureconfig

import magnolia._
import scala.language.experimental.macros
import scalaz._, Scalaz._

import pureconfig.error._

// WORKAROUND: https://github.com/pureconfig/pureconfig/issues/396
object MagnoliaConfigReader {
  type Typeclass[a] = ConfigReader[a]

  private val naming: ConfigFieldMapping =
    ConfigFieldMapping(CamelCase, KebabCase)

  def combine[A](ctx: CaseClass[ConfigReader, A]): ConfigReader[A] =
    c =>
      for {
        cur <- c.asObjectCursor
        bits <- ctx.parameters.toList.traverse { p =>
          val key = naming(p.label)
          val tc = p.typeclass
          cur.atKeyOrUndefined(key) match {
            case undefined if undefined.isUndefined =>
              p.default match {
                case Some(v) => Right(v)
                case None =>
                  tc match {
                    case _: AllowMissingKey => tc.from(undefined)
                    case _ => cur.failed(KeyNotFound.forKeys(key, cur.keys))
                  }
              }
            case defined => tc.from(defined)
          }
        }
      } yield ctx.rawConstruct(bits)

  def dispatch[A](ctx: SealedTrait[ConfigReader, A]): ConfigReader[A] =
    c =>
      for {
        cur <- c.asObjectCursor
        name <- cur.atKey("type").flatMap(_.asString)
        hit <- {
          ctx.subtypes
            .find(_.typeName.short.toLowerCase == name.toLowerCase)
            .toRight(ConfigReaderFailures(CannotParse(name, None)))
            .flatMap { s =>
              s.typeclass.from(c)
            }
        }
      } yield hit

  def gen[A]: ConfigReader[A] = macro Magnolia.gen[A]
}
pureconfig.ConfigReader=pureconfig.MagnoliaConfigReader.gen
Read more comments on GitHub >

github_iconTop Results From Across the Web

Automatic Differentiation Background - MATLAB & Simulink
The solve function uses automatic differentiation by default in problem-based optimization for general nonlinear objective functions and constraints; ...
Read more >
Build Your Own Automatic Differentiation Program
Imagine you've got some function you're playing around with, and you really want to know its derivative. If it's a relatively simple function, ......
Read more >
Automatic differentiation in PyTorch
In this article, we describe an automatic differentiation module of PyTorch — a library designed to enable rapid research on machine learning models....
Read more >
Introduction to gradients and automatic differentiation
The default behavior is to record all operations after accessing a trainable tf.Variable . The reasons for this are: ... # Not a...
Read more >
SuccessFactors Employee Central Event Reasons ...
... up event derivation rules that define the event reason according to what change is done to employee's data and the system automatically...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found